blob: d849e19c2fff9dcf49994d8f4619fab6f41cfb00 [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
Olli Etuaho95468d12017-05-04 11:14:34 +03001088 // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous
1089 // parsing steps. So it needs to be checked here.
1090 if (isMultiviewExtensionEnabled() && mShaderVersion < 300 && qualifier == EvqVertexIn)
1091 {
1092 error(location, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
1093 }
1094
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001095 bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut;
1096 if (mShaderVersion >= 310 && qualifier == EvqUniform)
1097 {
1098 canHaveLocation = true;
1099 // We're not checking whether the uniform location is in range here since that depends on
1100 // the type of the variable.
1101 // The type can only be fully determined for non-empty declarations.
1102 }
1103 if (!canHaveLocation)
1104 {
1105 checkLocationIsNotSpecified(location, layoutQualifier);
1106 }
1107}
1108
Martin Radevb8b01222016-11-20 23:25:53 +02001109void TParseContext::emptyDeclarationErrorCheck(const TPublicType &publicType,
1110 const TSourceLoc &location)
1111{
1112 if (publicType.isUnsizedArray())
1113 {
1114 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1115 // error. It is assumed that this applies to empty declarations as well.
1116 error(location, "empty array declaration needs to specify a size", "");
1117 }
Martin Radevb8b01222016-11-20 23:25:53 +02001118}
1119
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001120// These checks are done for all declarations that are non-empty. They're done for non-empty
1121// declarations starting a declarator list, and declarators that follow an empty declaration.
1122void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
1123 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -04001124{
Olli Etuahofa33d582015-04-09 14:33:12 +03001125 switch (publicType.qualifier)
1126 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001127 case EvqVaryingIn:
1128 case EvqVaryingOut:
1129 case EvqAttribute:
1130 case EvqVertexIn:
1131 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +03001132 case EvqComputeIn:
Martin Radev4a9cd802016-09-01 16:51:51 +03001133 if (publicType.getBasicType() == EbtStruct)
Jamie Madillb98c3a82015-07-23 14:26:04 -04001134 {
1135 error(identifierLocation, "cannot be used with a structure",
1136 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +03001137 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001138 }
Olli Etuahofa33d582015-04-09 14:33:12 +03001139
Jamie Madillb98c3a82015-07-23 14:26:04 -04001140 default:
1141 break;
Olli Etuahofa33d582015-04-09 14:33:12 +03001142 }
jchen10cc2a10e2017-05-03 14:05:12 +08001143 std::string reason(getBasicString(publicType.getBasicType()));
1144 reason += "s must be uniform";
Jamie Madillb98c3a82015-07-23 14:26:04 -04001145 if (publicType.qualifier != EvqUniform &&
jchen10cc2a10e2017-05-03 14:05:12 +08001146 !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str()))
Martin Radev2cc85b32016-08-05 16:22:53 +03001147 {
1148 return;
1149 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001150
Andrei Volykhina5527072017-03-22 16:46:30 +03001151 if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal &&
1152 publicType.qualifier != EvqConst) &&
1153 publicType.getBasicType() == EbtYuvCscStandardEXT)
1154 {
1155 error(identifierLocation, "cannot be used with a yuvCscStandardEXT",
1156 getQualifierString(publicType.qualifier));
1157 return;
1158 }
1159
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001160 if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform)
1161 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001162 // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized.
1163 // But invalid shaders may still reach here with an unsized array declaration.
1164 if (!publicType.isUnsizedArray())
1165 {
1166 TType type(publicType);
1167 checkUniformLocationInRange(identifierLocation, type.getLocationCount(),
1168 publicType.layoutQualifier);
1169 }
1170 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001171
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001172 // check for layout qualifier issues
1173 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
Andrei Volykhina5527072017-03-22 16:46:30 +03001174
Martin Radev2cc85b32016-08-05 16:22:53 +03001175 if (IsImage(publicType.getBasicType()))
1176 {
1177
1178 switch (layoutQualifier.imageInternalFormat)
1179 {
1180 case EiifRGBA32F:
1181 case EiifRGBA16F:
1182 case EiifR32F:
1183 case EiifRGBA8:
1184 case EiifRGBA8_SNORM:
1185 if (!IsFloatImage(publicType.getBasicType()))
1186 {
1187 error(identifierLocation,
1188 "internal image format requires a floating image type",
1189 getBasicString(publicType.getBasicType()));
1190 return;
1191 }
1192 break;
1193 case EiifRGBA32I:
1194 case EiifRGBA16I:
1195 case EiifRGBA8I:
1196 case EiifR32I:
1197 if (!IsIntegerImage(publicType.getBasicType()))
1198 {
1199 error(identifierLocation,
1200 "internal image format requires an integer image type",
1201 getBasicString(publicType.getBasicType()));
1202 return;
1203 }
1204 break;
1205 case EiifRGBA32UI:
1206 case EiifRGBA16UI:
1207 case EiifRGBA8UI:
1208 case EiifR32UI:
1209 if (!IsUnsignedImage(publicType.getBasicType()))
1210 {
1211 error(identifierLocation,
1212 "internal image format requires an unsigned image type",
1213 getBasicString(publicType.getBasicType()));
1214 return;
1215 }
1216 break;
1217 case EiifUnspecified:
1218 error(identifierLocation, "layout qualifier", "No image internal format specified");
1219 return;
1220 default:
1221 error(identifierLocation, "layout qualifier", "unrecognized token");
1222 return;
1223 }
1224
1225 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
1226 switch (layoutQualifier.imageInternalFormat)
1227 {
1228 case EiifR32F:
1229 case EiifR32I:
1230 case EiifR32UI:
1231 break;
1232 default:
1233 if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
1234 {
1235 error(identifierLocation, "layout qualifier",
1236 "Except for images with the r32f, r32i and r32ui format qualifiers, "
1237 "image variables must be qualified readonly and/or writeonly");
1238 return;
1239 }
1240 break;
1241 }
1242 }
1243 else
1244 {
Olli Etuaho43364892017-02-13 16:00:12 +00001245 checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat);
Martin Radev2cc85b32016-08-05 16:22:53 +03001246
Olli Etuaho43364892017-02-13 16:00:12 +00001247 checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
1248 }
1249}
Martin Radev2cc85b32016-08-05 16:22:53 +03001250
Olli Etuaho43364892017-02-13 16:00:12 +00001251void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type)
1252{
1253 TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
1254 int arraySize = type.isArray() ? type.getArraySize() : 1;
1255 if (IsImage(type.getBasicType()))
1256 {
1257 checkImageBindingIsValid(identifierLocation, layoutQualifier.binding, arraySize);
1258 }
1259 else if (IsSampler(type.getBasicType()))
1260 {
1261 checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding, arraySize);
1262 }
1263 else
1264 {
1265 ASSERT(!IsOpaqueType(type.getBasicType()));
1266 checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
Martin Radev2cc85b32016-08-05 16:22:53 +03001267 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001268}
1269
Olli Etuaho856c4972016-08-08 11:38:39 +03001270void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1271 const TString &layoutQualifierName,
1272 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001273{
1274
1275 if (mShaderVersion < versionRequired)
1276 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001277 error(location, "invalid layout qualifier: not supported", layoutQualifierName.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03001278 }
1279}
1280
Olli Etuaho856c4972016-08-08 11:38:39 +03001281bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1282 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001283{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001284 const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
Martin Radev802abe02016-08-04 17:48:32 +03001285 for (size_t i = 0u; i < localSize.size(); ++i)
1286 {
1287 if (localSize[i] != -1)
1288 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001289 error(location,
1290 "invalid layout qualifier: only valid when used with 'in' in a compute shader "
1291 "global layout declaration",
1292 getWorkGroupSizeString(i));
Olli Etuaho8a176262016-08-16 14:23:01 +03001293 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001294 }
1295 }
1296
Olli Etuaho8a176262016-08-16 14:23:01 +03001297 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001298}
1299
Olli Etuaho43364892017-02-13 16:00:12 +00001300void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
Martin Radev2cc85b32016-08-05 16:22:53 +03001301 TLayoutImageInternalFormat internalFormat)
1302{
1303 if (internalFormat != EiifUnspecified)
1304 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001305 error(location, "invalid layout qualifier: only valid when used with images",
1306 getImageInternalFormatString(internalFormat));
Martin Radev2cc85b32016-08-05 16:22:53 +03001307 }
Olli Etuaho43364892017-02-13 16:00:12 +00001308}
1309
1310void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
1311{
1312 if (binding != -1)
1313 {
1314 error(location,
1315 "invalid layout qualifier: only valid when used with opaque types or blocks",
1316 "binding");
1317 }
1318}
1319
1320void TParseContext::checkImageBindingIsValid(const TSourceLoc &location, int binding, int arraySize)
1321{
1322 // Expects arraySize to be 1 when setting binding for only a single variable.
1323 if (binding >= 0 && binding + arraySize > mMaxImageUnits)
1324 {
1325 error(location, "image binding greater than gl_MaxImageUnits", "binding");
1326 }
1327}
1328
1329void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location,
1330 int binding,
1331 int arraySize)
1332{
1333 // Expects arraySize to be 1 when setting binding for only a single variable.
1334 if (binding >= 0 && binding + arraySize > mMaxCombinedTextureImageUnits)
1335 {
1336 error(location, "sampler binding greater than maximum texture units", "binding");
1337 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001338}
1339
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001340void TParseContext::checkUniformLocationInRange(const TSourceLoc &location,
1341 int objectLocationCount,
1342 const TLayoutQualifier &layoutQualifier)
1343{
1344 int loc = layoutQualifier.location;
1345 if (loc >= 0 && loc + objectLocationCount > mMaxUniformLocations)
1346 {
1347 error(location, "Uniform location out of range", "location");
1348 }
1349}
1350
Andrei Volykhina5527072017-03-22 16:46:30 +03001351void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv)
1352{
1353 if (yuv != false)
1354 {
1355 error(location, "invalid layout qualifier: only valid on program outputs", "yuv");
1356 }
1357}
1358
Olli Etuaho383b7912016-08-05 11:22:59 +03001359void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
Olli Etuaho856c4972016-08-08 11:38:39 +03001360 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001361{
1362 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1363 {
1364 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1365 if (qual == EvqOut || qual == EvqInOut)
1366 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001367 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho8a176262016-08-16 14:23:01 +03001368 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001369 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001370 error(argument->getLine(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00001371 "Constant value cannot be passed for 'out' or 'inout' parameters.",
Olli Etuahoec9232b2017-03-27 17:01:37 +03001372 fnCall->getFunctionSymbolInfo()->getName().c_str());
Olli Etuaho383b7912016-08-05 11:22:59 +03001373 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001374 }
1375 }
1376 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001377}
1378
Martin Radev70866b82016-07-22 15:27:42 +03001379void TParseContext::checkInvariantVariableQualifier(bool invariant,
1380 const TQualifier qualifier,
1381 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001382{
Martin Radev70866b82016-07-22 15:27:42 +03001383 if (!invariant)
1384 return;
1385
1386 if (mShaderVersion < 300)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001387 {
Martin Radev70866b82016-07-22 15:27:42 +03001388 // input variables in the fragment shader can be also qualified as invariant
1389 if (!sh::CanBeInvariantESSL1(qualifier))
1390 {
1391 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1392 }
1393 }
1394 else
1395 {
1396 if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
1397 {
1398 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1399 }
Olli Etuaho37ad4742015-04-27 13:18:50 +03001400 }
1401}
1402
Arun Patole7e7e68d2015-05-22 12:02:25 +05301403bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001404{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001405 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001406 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1407 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001408}
1409
Arun Patole7e7e68d2015-05-22 12:02:25 +05301410bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001411{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001412 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001413}
1414
Jamie Madillb98c3a82015-07-23 14:26:04 -04001415void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1416 const char *extName,
1417 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001418{
1419 pp::SourceLocation srcLoc;
1420 srcLoc.file = loc.first_file;
1421 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001422 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001423}
1424
Jamie Madillb98c3a82015-07-23 14:26:04 -04001425void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1426 const char *name,
1427 const char *value,
1428 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001429{
1430 pp::SourceLocation srcLoc;
1431 srcLoc.file = loc.first_file;
1432 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001433 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001434}
1435
Martin Radev4c4c8e72016-08-04 12:25:34 +03001436sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
Martin Radev802abe02016-08-04 17:48:32 +03001437{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001438 sh::WorkGroupSize result;
Martin Radev802abe02016-08-04 17:48:32 +03001439 for (size_t i = 0u; i < result.size(); ++i)
1440 {
1441 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1442 {
1443 result[i] = 1;
1444 }
1445 else
1446 {
1447 result[i] = mComputeShaderLocalSize[i];
1448 }
1449 }
1450 return result;
1451}
1452
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001453/////////////////////////////////////////////////////////////////////////////////
1454//
1455// Non-Errors.
1456//
1457/////////////////////////////////////////////////////////////////////////////////
1458
Jamie Madill5c097022014-08-20 16:38:32 -04001459const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1460 const TString *name,
1461 const TSymbol *symbol)
1462{
Yunchao Hed7297bf2017-04-19 15:27:10 +08001463 const TVariable *variable = nullptr;
Jamie Madill5c097022014-08-20 16:38:32 -04001464
1465 if (!symbol)
1466 {
1467 error(location, "undeclared identifier", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001468 }
1469 else if (!symbol->isVariable())
1470 {
1471 error(location, "variable expected", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001472 }
1473 else
1474 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001475 variable = static_cast<const TVariable *>(symbol);
Jamie Madill5c097022014-08-20 16:38:32 -04001476
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001477 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
Olli Etuaho383b7912016-08-05 11:22:59 +03001478 !variable->getExtension().empty())
Jamie Madill5c097022014-08-20 16:38:32 -04001479 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001480 checkCanUseExtension(location, variable->getExtension());
Jamie Madill5c097022014-08-20 16:38:32 -04001481 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001482
1483 // Reject shaders using both gl_FragData and gl_FragColor
1484 TQualifier qualifier = variable->getType().getQualifier();
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001485 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001486 {
1487 mUsesFragData = true;
1488 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001489 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001490 {
1491 mUsesFragColor = true;
1492 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001493 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1494 {
1495 mUsesSecondaryOutputs = true;
1496 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001497
1498 // This validation is not quite correct - it's only an error to write to
1499 // both FragData and FragColor. For simplicity, and because users shouldn't
1500 // be rewarded for reading from undefined varaibles, return an error
1501 // if they are both referenced, rather than assigned.
1502 if (mUsesFragData && mUsesFragColor)
1503 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001504 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1505 if (mUsesSecondaryOutputs)
1506 {
1507 errorMessage =
1508 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1509 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1510 }
1511 error(location, errorMessage, name->c_str());
Jamie Madill14e95b32015-05-07 10:10:41 -04001512 }
Martin Radevb0883602016-08-04 17:48:58 +03001513
1514 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1515 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1516 qualifier == EvqWorkGroupSize)
1517 {
1518 error(location,
1519 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1520 "gl_WorkGroupSize");
1521 }
Jamie Madill5c097022014-08-20 16:38:32 -04001522 }
1523
1524 if (!variable)
1525 {
1526 TType type(EbtFloat, EbpUndefined);
1527 TVariable *fakeVariable = new TVariable(name, type);
1528 symbolTable.declare(fakeVariable);
1529 variable = fakeVariable;
1530 }
1531
1532 return variable;
1533}
1534
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001535TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1536 const TString *name,
1537 const TSymbol *symbol)
1538{
1539 const TVariable *variable = getNamedVariable(location, name, symbol);
1540
Olli Etuaho09b04a22016-12-15 13:30:26 +00001541 if (variable->getType().getQualifier() == EvqViewIDOVR && IsWebGLBasedSpec(mShaderSpec) &&
1542 mShaderType == GL_FRAGMENT_SHADER && !isExtensionEnabled("GL_OVR_multiview2"))
1543 {
1544 // WEBGL_multiview spec
1545 error(location, "Need to enable OVR_multiview2 to use gl_ViewID_OVR in fragment shader",
1546 "gl_ViewID_OVR");
1547 }
1548
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001549 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001550 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001551 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001552 return intermediate.addConstantUnion(constArray, variable->getType(), location);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001553 }
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001554 else if (variable->getType().getQualifier() == EvqWorkGroupSize &&
1555 mComputeShaderLocalSizeDeclared)
1556 {
1557 // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
1558 // needs to be added to the AST as a constant and not as a symbol.
1559 sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
1560 TConstantUnion *constArray = new TConstantUnion[3];
1561 for (size_t i = 0; i < 3; ++i)
1562 {
1563 constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
1564 }
1565
1566 ASSERT(variable->getType().getBasicType() == EbtUInt);
1567 ASSERT(variable->getType().getObjectSize() == 3);
1568
1569 TType type(variable->getType());
1570 type.setQualifier(EvqConst);
1571 return intermediate.addConstantUnion(constArray, type, location);
1572 }
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001573 else
1574 {
1575 return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
1576 variable->getType(), location);
1577 }
1578}
1579
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001580//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001581// Initializers show up in several places in the grammar. Have one set of
1582// code to handle them here.
1583//
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001584// Returns true on error, false if no error
1585//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001586bool TParseContext::executeInitializer(const TSourceLoc &line,
1587 const TString &identifier,
1588 const TPublicType &pType,
1589 TIntermTyped *initializer,
Olli Etuaho13389b62016-10-16 11:48:18 +01001590 TIntermBinary **initNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001591{
Olli Etuaho13389b62016-10-16 11:48:18 +01001592 ASSERT(initNode != nullptr);
1593 ASSERT(*initNode == nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001594 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001595
Olli Etuaho2935c582015-04-08 14:32:06 +03001596 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001597 if (type.isUnsizedArray())
1598 {
Olli Etuaho02bd82c2016-11-03 10:29:43 +00001599 // We have not checked yet whether the initializer actually is an array or not.
1600 if (initializer->isArray())
1601 {
1602 type.setArraySize(initializer->getArraySize());
1603 }
1604 else
1605 {
1606 // Having a non-array initializer for an unsized array will result in an error later,
1607 // so we don't generate an error message here.
1608 type.setArraySize(1u);
1609 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03001610 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001611 if (!declareVariable(line, identifier, type, &variable))
1612 {
1613 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001614 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001615
Olli Etuahob0c645e2015-05-12 14:25:36 +03001616 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001617 if (symbolTable.atGlobalLevel() &&
1618 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001619 {
1620 // Error message does not completely match behavior with ESSL 1.00, but
1621 // we want to steer developers towards only using constant expressions.
1622 error(line, "global variable initializers must be constant expressions", "=");
1623 return true;
1624 }
1625 if (globalInitWarning)
1626 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001627 warning(
1628 line,
1629 "global variable initializers should be constant expressions "
1630 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1631 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001632 }
1633
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001634 //
1635 // identifier must be of type constant, a global, or a temporary
1636 //
1637 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301638 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1639 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001640 error(line, " cannot initialize this type of qualifier ",
1641 variable->getType().getQualifierString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001642 return true;
1643 }
1644 //
1645 // test for and propagate constant
1646 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001647
Arun Patole7e7e68d2015-05-22 12:02:25 +05301648 if (qualifier == EvqConst)
1649 {
1650 if (qualifier != initializer->getType().getQualifier())
1651 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001652 std::stringstream reasonStream;
1653 reasonStream << "assigning non-constant to '" << variable->getType().getCompleteString()
1654 << "'";
1655 std::string reason = reasonStream.str();
1656 error(line, reason.c_str(), "=");
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 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301660 if (type != initializer->getType())
1661 {
1662 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001663 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001664 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001665 return true;
1666 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001667
1668 // Save the constant folded value to the variable if possible. For example array
1669 // initializers are not folded, since that way copying the array literal to multiple places
1670 // in the shader is avoided.
1671 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1672 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301673 if (initializer->getAsConstantUnion())
1674 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001675 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuaho13389b62016-10-16 11:48:18 +01001676 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001677 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301678 }
1679 else if (initializer->getAsSymbolNode())
1680 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001681 const TSymbol *symbol =
1682 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1683 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001684
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001685 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001686 if (constArray)
1687 {
1688 variable->shareConstPointer(constArray);
Olli Etuaho13389b62016-10-16 11:48:18 +01001689 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001690 return false;
1691 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001692 }
1693 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001694
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001695 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1696 variable->getUniqueId(), variable->getName(), variable->getType(), line);
Olli Etuaho13389b62016-10-16 11:48:18 +01001697 *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1698 if (*initNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001699 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001700 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1701 return true;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001702 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001703
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001704 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001705}
1706
Olli Etuaho0e3aee32016-10-27 12:56:38 +01001707void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
1708{
1709 checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
1710 typeSpecifier->getBasicType());
1711
1712 if (mShaderVersion < 300 && typeSpecifier->array)
1713 {
1714 error(typeSpecifier->getLine(), "not supported", "first-class array");
1715 typeSpecifier->clearArrayness();
1716 }
1717}
1718
Martin Radev70866b82016-07-22 15:27:42 +03001719TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301720 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001721{
Olli Etuaho77ba4082016-12-16 12:01:18 +00001722 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001723
Martin Radev70866b82016-07-22 15:27:42 +03001724 TPublicType returnType = typeSpecifier;
1725 returnType.qualifier = typeQualifier.qualifier;
1726 returnType.invariant = typeQualifier.invariant;
1727 returnType.layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03001728 returnType.memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03001729 returnType.precision = typeSpecifier.precision;
1730
1731 if (typeQualifier.precision != EbpUndefined)
1732 {
1733 returnType.precision = typeQualifier.precision;
1734 }
1735
Martin Radev4a9cd802016-09-01 16:51:51 +03001736 checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
1737 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03001738
Martin Radev4a9cd802016-09-01 16:51:51 +03001739 checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
1740 typeSpecifier.getLine());
Martin Radev70866b82016-07-22 15:27:42 +03001741
Martin Radev4a9cd802016-09-01 16:51:51 +03001742 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001743
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001744 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001745 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001746 if (typeSpecifier.array)
1747 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001748 error(typeSpecifier.getLine(), "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001749 returnType.clearArrayness();
1750 }
1751
Martin Radev70866b82016-07-22 15:27:42 +03001752 if (returnType.qualifier == EvqAttribute &&
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 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001758
Martin Radev70866b82016-07-22 15:27:42 +03001759 if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001760 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001761 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001762 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001763 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001764 }
1765 }
1766 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001767 {
Martin Radev70866b82016-07-22 15:27:42 +03001768 if (!returnType.layoutQualifier.isEmpty())
Olli Etuahoabb0c382015-07-13 12:01:12 +03001769 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001770 checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03001771 }
Martin Radev70866b82016-07-22 15:27:42 +03001772 if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
1773 returnType.qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001774 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001775 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
1776 typeSpecifier.getLine());
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001777 }
Martin Radev70866b82016-07-22 15:27:42 +03001778 if (returnType.qualifier == EvqComputeIn)
Martin Radev802abe02016-08-04 17:48:32 +03001779 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001780 error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
Martin Radev802abe02016-08-04 17:48:32 +03001781 "in");
Martin Radev802abe02016-08-04 17:48:32 +03001782 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001783 }
1784
1785 return returnType;
1786}
1787
Olli Etuaho856c4972016-08-08 11:38:39 +03001788void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1789 const TPublicType &type,
1790 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03001791{
1792 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
Martin Radev4a9cd802016-09-01 16:51:51 +03001793 if (type.getBasicType() == EbtBool)
Olli Etuahocc36b982015-07-10 14:14:18 +03001794 {
1795 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001796 }
1797
1798 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1799 switch (qualifier)
1800 {
1801 case EvqVertexIn:
1802 // ESSL 3.00 section 4.3.4
1803 if (type.array)
1804 {
1805 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001806 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001807 // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03001808 return;
1809 case EvqFragmentOut:
1810 // ESSL 3.00 section 4.3.6
Martin Radev4a9cd802016-09-01 16:51:51 +03001811 if (type.typeSpecifierNonArray.isMatrix())
Olli Etuahocc36b982015-07-10 14:14:18 +03001812 {
1813 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001814 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001815 // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03001816 return;
1817 default:
1818 break;
1819 }
1820
1821 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1822 // restrictions.
1823 bool typeContainsIntegers =
Martin Radev4a9cd802016-09-01 16:51:51 +03001824 (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
1825 type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
Olli Etuahocc36b982015-07-10 14:14:18 +03001826 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1827 {
1828 error(qualifierLocation, "must use 'flat' interpolation here",
1829 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001830 }
1831
Martin Radev4a9cd802016-09-01 16:51:51 +03001832 if (type.getBasicType() == EbtStruct)
Olli Etuahocc36b982015-07-10 14:14:18 +03001833 {
1834 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1835 // These restrictions are only implied by the ESSL 3.00 spec, but
1836 // the ESSL 3.10 spec lists these restrictions explicitly.
1837 if (type.array)
1838 {
1839 error(qualifierLocation, "cannot be an array of structures",
1840 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001841 }
1842 if (type.isStructureContainingArrays())
1843 {
1844 error(qualifierLocation, "cannot be a structure containing an array",
1845 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001846 }
1847 if (type.isStructureContainingType(EbtStruct))
1848 {
1849 error(qualifierLocation, "cannot be a structure containing a structure",
1850 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001851 }
1852 if (type.isStructureContainingType(EbtBool))
1853 {
1854 error(qualifierLocation, "cannot be a structure containing a bool",
1855 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001856 }
1857 }
1858}
1859
Martin Radev2cc85b32016-08-05 16:22:53 +03001860void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
1861{
1862 if (qualifier.getType() == QtStorage)
1863 {
1864 const TStorageQualifierWrapper &storageQualifier =
1865 static_cast<const TStorageQualifierWrapper &>(qualifier);
1866 if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
1867 !symbolTable.atGlobalLevel())
1868 {
1869 error(storageQualifier.getLine(),
1870 "Local variables can only use the const storage qualifier.",
1871 storageQualifier.getQualifierString().c_str());
1872 }
1873 }
1874}
1875
Olli Etuaho43364892017-02-13 16:00:12 +00001876void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
Martin Radev2cc85b32016-08-05 16:22:53 +03001877 const TSourceLoc &location)
1878{
1879 if (memoryQualifier.readonly)
1880 {
1881 error(location, "Only allowed with images.", "readonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03001882 }
1883 if (memoryQualifier.writeonly)
1884 {
1885 error(location, "Only allowed with images.", "writeonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03001886 }
Martin Radev049edfa2016-11-11 14:35:37 +02001887 if (memoryQualifier.coherent)
1888 {
1889 error(location, "Only allowed with images.", "coherent");
Martin Radev049edfa2016-11-11 14:35:37 +02001890 }
1891 if (memoryQualifier.restrictQualifier)
1892 {
1893 error(location, "Only allowed with images.", "restrict");
Martin Radev049edfa2016-11-11 14:35:37 +02001894 }
1895 if (memoryQualifier.volatileQualifier)
1896 {
1897 error(location, "Only allowed with images.", "volatile");
Martin Radev049edfa2016-11-11 14:35:37 +02001898 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001899}
1900
Olli Etuaho13389b62016-10-16 11:48:18 +01001901TIntermDeclaration *TParseContext::parseSingleDeclaration(
1902 TPublicType &publicType,
1903 const TSourceLoc &identifierOrTypeLocation,
1904 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04001905{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001906 TType type(publicType);
1907 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
1908 mDirectiveHandler.pragma().stdgl.invariantAll)
1909 {
1910 TQualifier qualifier = type.getQualifier();
1911
1912 // The directive handler has already taken care of rejecting invalid uses of this pragma
1913 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
1914 // affected variable declarations:
1915 //
1916 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
1917 // elsewhere, in TranslatorGLSL.)
1918 //
1919 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
1920 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
1921 // the way this is currently implemented we have to enable this compiler option before
1922 // parsing the shader and determining the shading language version it uses. If this were
1923 // implemented as a post-pass, the workaround could be more targeted.
1924 //
1925 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
1926 // the specification, but there are desktop OpenGL drivers that expect that this is the
1927 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
1928 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
1929 {
1930 type.setInvariant(true);
1931 }
1932 }
1933
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001934 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
1935 identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001936
Olli Etuahobab4c082015-04-24 16:38:49 +03001937 bool emptyDeclaration = (identifier == "");
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001938 mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration;
Olli Etuahofa33d582015-04-09 14:33:12 +03001939
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001940 TIntermSymbol *symbol = nullptr;
Olli Etuahobab4c082015-04-24 16:38:49 +03001941 if (emptyDeclaration)
1942 {
Martin Radevb8b01222016-11-20 23:25:53 +02001943 emptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001944 // In most cases we don't need to create a symbol node for an empty declaration.
1945 // But if the empty declaration is declaring a struct type, the symbol node will store that.
1946 if (type.getBasicType() == EbtStruct)
1947 {
1948 symbol = intermediate.addSymbol(0, "", type, identifierOrTypeLocation);
1949 }
Olli Etuahobab4c082015-04-24 16:38:49 +03001950 }
1951 else
Jamie Madill60ed9812013-06-06 11:56:46 -04001952 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001953 nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001954
Olli Etuaho856c4972016-08-08 11:38:39 +03001955 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001956
Olli Etuaho2935c582015-04-08 14:32:06 +03001957 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001958 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001959
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001960 if (variable)
Olli Etuaho13389b62016-10-16 11:48:18 +01001961 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001962 symbol = intermediate.addSymbol(variable->getUniqueId(), identifier, type,
1963 identifierOrTypeLocation);
Olli Etuaho13389b62016-10-16 11:48:18 +01001964 }
Jamie Madill60ed9812013-06-06 11:56:46 -04001965 }
1966
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001967 TIntermDeclaration *declaration = new TIntermDeclaration();
1968 declaration->setLine(identifierOrTypeLocation);
1969 if (symbol)
1970 {
1971 declaration->appendDeclarator(symbol);
1972 }
Olli Etuaho13389b62016-10-16 11:48:18 +01001973 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04001974}
1975
Olli Etuaho13389b62016-10-16 11:48:18 +01001976TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1977 const TSourceLoc &identifierLocation,
1978 const TString &identifier,
1979 const TSourceLoc &indexLocation,
1980 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04001981{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001982 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03001983
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001984 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
1985 identifierLocation);
1986
1987 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001988
Olli Etuaho856c4972016-08-08 11:38:39 +03001989 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001990
Olli Etuaho8a176262016-08-16 14:23:01 +03001991 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001992
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001993 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001994
Olli Etuaho856c4972016-08-08 11:38:39 +03001995 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001996 // Make the type an array even if size check failed.
1997 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1998 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04001999
Olli Etuaho2935c582015-04-08 14:32:06 +03002000 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002001 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04002002
Olli Etuaho13389b62016-10-16 11:48:18 +01002003 TIntermDeclaration *declaration = new TIntermDeclaration();
2004 declaration->setLine(identifierLocation);
2005
Olli Etuahoe7847b02015-03-16 11:56:12 +02002006 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002007 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002008 {
Jamie Madill60ed9812013-06-06 11:56:46 -04002009 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002010 declaration->appendDeclarator(symbol);
2011 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002012
Olli Etuaho13389b62016-10-16 11:48:18 +01002013 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002014}
2015
Olli Etuaho13389b62016-10-16 11:48:18 +01002016TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
2017 const TSourceLoc &identifierLocation,
2018 const TString &identifier,
2019 const TSourceLoc &initLocation,
2020 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04002021{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002022 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002023
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002024 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2025 identifierLocation);
2026
2027 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002028
Olli Etuaho13389b62016-10-16 11:48:18 +01002029 TIntermDeclaration *declaration = new TIntermDeclaration();
2030 declaration->setLine(identifierLocation);
2031
2032 TIntermBinary *initNode = nullptr;
2033 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04002034 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002035 if (initNode)
2036 {
2037 declaration->appendDeclarator(initNode);
2038 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002039 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002040 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002041}
2042
Olli Etuaho13389b62016-10-16 11:48:18 +01002043TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
Jamie Madillb98c3a82015-07-23 14:26:04 -04002044 TPublicType &publicType,
2045 const TSourceLoc &identifierLocation,
2046 const TString &identifier,
2047 const TSourceLoc &indexLocation,
2048 TIntermTyped *indexExpression,
2049 const TSourceLoc &initLocation,
2050 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002051{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002052 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002053
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002054 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2055 identifierLocation);
2056
2057 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002058
Olli Etuaho8a176262016-08-16 14:23:01 +03002059 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002060
2061 TPublicType arrayType(publicType);
2062
Olli Etuaho856c4972016-08-08 11:38:39 +03002063 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002064 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2065 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002066 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002067 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002068 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002069 }
2070 // Make the type an array even if size check failed.
2071 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2072 arrayType.setArraySize(size);
2073
Olli Etuaho13389b62016-10-16 11:48:18 +01002074 TIntermDeclaration *declaration = new TIntermDeclaration();
2075 declaration->setLine(identifierLocation);
2076
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002077 // initNode will correspond to the whole of "type b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002078 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002079 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2080 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002081 if (initNode)
2082 {
2083 declaration->appendDeclarator(initNode);
2084 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002085 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002086
2087 return declaration;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002088}
2089
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002090TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
Martin Radev70866b82016-07-22 15:27:42 +03002091 const TTypeQualifierBuilder &typeQualifierBuilder,
2092 const TSourceLoc &identifierLoc,
2093 const TString *identifier,
2094 const TSymbol *symbol)
Jamie Madill47e3ec02014-08-20 16:38:33 -04002095{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002096 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002097
Martin Radev70866b82016-07-22 15:27:42 +03002098 if (!typeQualifier.invariant)
2099 {
2100 error(identifierLoc, "Expected invariant", identifier->c_str());
2101 return nullptr;
2102 }
2103 if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
2104 {
2105 return nullptr;
2106 }
Jamie Madill47e3ec02014-08-20 16:38:33 -04002107 if (!symbol)
2108 {
2109 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002110 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04002111 }
Martin Radev70866b82016-07-22 15:27:42 +03002112 if (!IsQualifierUnspecified(typeQualifier.qualifier))
Jamie Madill47e3ec02014-08-20 16:38:33 -04002113 {
Martin Radev70866b82016-07-22 15:27:42 +03002114 error(identifierLoc, "invariant declaration specifies qualifier",
2115 getQualifierString(typeQualifier.qualifier));
Jamie Madill47e3ec02014-08-20 16:38:33 -04002116 }
Martin Radev70866b82016-07-22 15:27:42 +03002117 if (typeQualifier.precision != EbpUndefined)
2118 {
2119 error(identifierLoc, "invariant declaration specifies precision",
2120 getPrecisionString(typeQualifier.precision));
2121 }
2122 if (!typeQualifier.layoutQualifier.isEmpty())
2123 {
2124 error(identifierLoc, "invariant declaration specifies layout", "'layout'");
2125 }
2126
2127 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
2128 ASSERT(variable);
2129 const TType &type = variable->getType();
2130
2131 checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
2132 typeQualifier.line);
Olli Etuaho43364892017-02-13 16:00:12 +00002133 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev70866b82016-07-22 15:27:42 +03002134
2135 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
2136
2137 TIntermSymbol *intermSymbol =
2138 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
2139
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002140 return new TIntermInvariantDeclaration(intermSymbol, identifierLoc);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002141}
2142
Olli Etuaho13389b62016-10-16 11:48:18 +01002143void TParseContext::parseDeclarator(TPublicType &publicType,
2144 const TSourceLoc &identifierLocation,
2145 const TString &identifier,
2146 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002147{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002148 // If the declaration starting this declarator list was empty (example: int,), some checks were
2149 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002150 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002151 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002152 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2153 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002154 }
2155
Olli Etuaho856c4972016-08-08 11:38:39 +03002156 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002157
Olli Etuaho856c4972016-08-08 11:38:39 +03002158 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002159
Olli Etuaho2935c582015-04-08 14:32:06 +03002160 TVariable *variable = nullptr;
Olli Etuaho43364892017-02-13 16:00:12 +00002161 TType type(publicType);
2162 declareVariable(identifierLocation, identifier, type, &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002163
Olli Etuaho43364892017-02-13 16:00:12 +00002164 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002165 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002166 {
Jamie Madill502d66f2013-06-20 11:55:52 -04002167 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002168 declarationOut->appendDeclarator(symbol);
2169 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002170}
2171
Olli Etuaho13389b62016-10-16 11:48:18 +01002172void TParseContext::parseArrayDeclarator(TPublicType &publicType,
2173 const TSourceLoc &identifierLocation,
2174 const TString &identifier,
2175 const TSourceLoc &arrayLocation,
2176 TIntermTyped *indexExpression,
2177 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002178{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002179 // If the declaration starting this declarator list was empty (example: int,), some checks were
2180 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002181 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002182 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002183 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2184 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002185 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002186
Olli Etuaho856c4972016-08-08 11:38:39 +03002187 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002188
Olli Etuaho856c4972016-08-08 11:38:39 +03002189 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002190
Olli Etuaho8a176262016-08-16 14:23:01 +03002191 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04002192 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002193 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03002194 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03002195 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002196
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002197 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002198 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04002199
Jamie Madillb98c3a82015-07-23 14:26:04 -04002200 TIntermSymbol *symbol =
2201 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002202 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002203 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002204
Olli Etuaho13389b62016-10-16 11:48:18 +01002205 declarationOut->appendDeclarator(symbol);
Jamie Madill502d66f2013-06-20 11:55:52 -04002206 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002207}
2208
Olli Etuaho13389b62016-10-16 11:48:18 +01002209void TParseContext::parseInitDeclarator(const TPublicType &publicType,
2210 const TSourceLoc &identifierLocation,
2211 const TString &identifier,
2212 const TSourceLoc &initLocation,
2213 TIntermTyped *initializer,
2214 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002215{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002216 // If the declaration starting this declarator list was empty (example: int,), some checks were
2217 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002218 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002219 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002220 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2221 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002222 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002223
Olli Etuaho856c4972016-08-08 11:38:39 +03002224 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002225
Olli Etuaho13389b62016-10-16 11:48:18 +01002226 TIntermBinary *initNode = nullptr;
2227 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04002228 {
2229 //
2230 // build the intermediate representation
2231 //
Olli Etuaho13389b62016-10-16 11:48:18 +01002232 if (initNode)
Jamie Madill502d66f2013-06-20 11:55:52 -04002233 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002234 declarationOut->appendDeclarator(initNode);
Jamie Madill502d66f2013-06-20 11:55:52 -04002235 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002236 }
2237}
2238
Olli Etuaho13389b62016-10-16 11:48:18 +01002239void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
2240 const TSourceLoc &identifierLocation,
2241 const TString &identifier,
2242 const TSourceLoc &indexLocation,
2243 TIntermTyped *indexExpression,
2244 const TSourceLoc &initLocation,
2245 TIntermTyped *initializer,
2246 TIntermDeclaration *declarationOut)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002247{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002248 // If the declaration starting this declarator list was empty (example: int,), some checks were
2249 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002250 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002251 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002252 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2253 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002254 }
2255
Olli Etuaho856c4972016-08-08 11:38:39 +03002256 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002257
Olli Etuaho8a176262016-08-16 14:23:01 +03002258 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002259
2260 TPublicType arrayType(publicType);
2261
Olli Etuaho856c4972016-08-08 11:38:39 +03002262 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002263 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2264 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002265 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002266 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002267 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002268 }
2269 // Make the type an array even if size check failed.
2270 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2271 arrayType.setArraySize(size);
2272
2273 // initNode will correspond to the whole of "b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002274 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002275 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2276 {
2277 if (initNode)
2278 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002279 declarationOut->appendDeclarator(initNode);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002280 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002281 }
2282}
2283
Martin Radev70866b82016-07-22 15:27:42 +03002284void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
Jamie Madilla295edf2013-06-06 11:56:48 -04002285{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002286 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madilla295edf2013-06-06 11:56:48 -04002287 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04002288
Martin Radev70866b82016-07-22 15:27:42 +03002289 checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
2290 typeQualifier.line);
2291
Jamie Madillc2128ff2016-07-04 10:26:17 -04002292 // It should never be the case, but some strange parser errors can send us here.
2293 if (layoutQualifier.isEmpty())
2294 {
2295 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04002296 return;
2297 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002298
Martin Radev802abe02016-08-04 17:48:32 +03002299 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04002300 {
Olli Etuaho43364892017-02-13 16:00:12 +00002301 error(typeQualifier.line, "invalid layout qualifier combination", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04002302 return;
2303 }
2304
Olli Etuaho43364892017-02-13 16:00:12 +00002305 checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);
2306
2307 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev2cc85b32016-08-05 16:22:53 +03002308
2309 checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
2310
Andrei Volykhina5527072017-03-22 16:46:30 +03002311 checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv);
2312
Martin Radev802abe02016-08-04 17:48:32 +03002313 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04002314 {
Martin Radev802abe02016-08-04 17:48:32 +03002315 if (mComputeShaderLocalSizeDeclared &&
2316 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
2317 {
2318 error(typeQualifier.line, "Work group size does not match the previous declaration",
2319 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002320 return;
2321 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002322
Martin Radev802abe02016-08-04 17:48:32 +03002323 if (mShaderVersion < 310)
2324 {
2325 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002326 return;
2327 }
Jamie Madill099c0f32013-06-20 11:55:52 -04002328
Martin Radev4c4c8e72016-08-04 12:25:34 +03002329 if (!layoutQualifier.localSize.isAnyValueSet())
Martin Radev802abe02016-08-04 17:48:32 +03002330 {
2331 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002332 return;
2333 }
2334
2335 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
2336 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
2337
2338 const TConstantUnion *maxComputeWorkGroupSizeData =
2339 maxComputeWorkGroupSize->getConstPointer();
2340
2341 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
2342 {
2343 if (layoutQualifier.localSize[i] != -1)
2344 {
2345 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
2346 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
2347 if (mComputeShaderLocalSize[i] < 1 ||
2348 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
2349 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002350 std::stringstream reasonStream;
2351 reasonStream << "invalid value: Value must be at least 1 and no greater than "
2352 << maxComputeWorkGroupSizeValue;
2353 const std::string &reason = reasonStream.str();
Martin Radev802abe02016-08-04 17:48:32 +03002354
Olli Etuaho4de340a2016-12-16 09:32:03 +00002355 error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03002356 return;
2357 }
2358 }
2359 }
2360
2361 mComputeShaderLocalSizeDeclared = true;
2362 }
Olli Etuaho95468d12017-05-04 11:14:34 +03002363 else if (isMultiviewExtensionEnabled() && typeQualifier.qualifier == EvqVertexIn)
Olli Etuaho09b04a22016-12-15 13:30:26 +00002364 {
2365 // This error is only specified in WebGL, but tightens unspecified behavior in the native
2366 // specification.
2367 if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
2368 {
2369 error(typeQualifier.line, "Number of views does not match the previous declaration",
2370 "layout");
2371 return;
2372 }
2373
2374 if (layoutQualifier.numViews == -1)
2375 {
2376 error(typeQualifier.line, "No num_views specified", "layout");
2377 return;
2378 }
2379
2380 if (layoutQualifier.numViews > mMaxNumViews)
2381 {
2382 error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
2383 "layout");
2384 return;
2385 }
2386
2387 mNumViews = layoutQualifier.numViews;
2388 }
Martin Radev802abe02016-08-04 17:48:32 +03002389 else
Jamie Madill1566ef72013-06-20 11:55:54 -04002390 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00002391 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03002392 {
Martin Radev802abe02016-08-04 17:48:32 +03002393 return;
2394 }
2395
2396 if (typeQualifier.qualifier != EvqUniform)
2397 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002398 error(typeQualifier.line, "invalid qualifier: global layout must be uniform",
2399 getQualifierString(typeQualifier.qualifier));
Martin Radev802abe02016-08-04 17:48:32 +03002400 return;
2401 }
2402
2403 if (mShaderVersion < 300)
2404 {
2405 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
2406 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002407 return;
2408 }
2409
Olli Etuaho09b04a22016-12-15 13:30:26 +00002410 checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002411
2412 if (layoutQualifier.matrixPacking != EmpUnspecified)
2413 {
2414 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
2415 }
2416
2417 if (layoutQualifier.blockStorage != EbsUnspecified)
2418 {
2419 mDefaultBlockStorage = layoutQualifier.blockStorage;
2420 }
Jamie Madill1566ef72013-06-20 11:55:54 -04002421 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002422}
2423
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002424TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
2425 const TFunction &function,
2426 const TSourceLoc &location,
2427 bool insertParametersToSymbolTable)
2428{
Olli Etuahofe486322017-03-21 09:30:54 +00002429 TIntermFunctionPrototype *prototype =
2430 new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function));
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002431 // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
2432 // point to the data that already exists in the symbol table.
2433 prototype->getFunctionSymbolInfo()->setFromFunction(function);
2434 prototype->setLine(location);
2435
2436 for (size_t i = 0; i < function.getParamCount(); i++)
2437 {
2438 const TConstParameter &param = function.getParam(i);
2439
2440 // If the parameter has no name, it's not an error, just don't add it to symbol table (could
2441 // be used for unused args).
2442 if (param.name != nullptr)
2443 {
2444 TVariable *variable = new TVariable(param.name, *param.type);
2445
2446 // Insert the parameter in the symbol table.
2447 if (insertParametersToSymbolTable && !symbolTable.declare(variable))
2448 {
2449 error(location, "redefinition", variable->getName().c_str());
2450 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2451 continue;
2452 }
2453 TIntermSymbol *symbol = intermediate.addSymbol(
2454 variable->getUniqueId(), variable->getName(), variable->getType(), location);
2455 prototype->appendParameter(symbol);
2456 }
2457 else
2458 {
2459 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2460 }
2461 }
2462 return prototype;
2463}
2464
Olli Etuaho16c745a2017-01-16 17:02:27 +00002465TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
2466 const TFunction &parsedFunction,
2467 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002468{
Olli Etuaho476197f2016-10-11 13:59:08 +01002469 // Note: function found from the symbol table could be the same as parsedFunction if this is the
2470 // first declaration. Either way the instance in the symbol table is used to track whether the
2471 // function is declared multiple times.
2472 TFunction *function = static_cast<TFunction *>(
2473 symbolTable.find(parsedFunction.getMangledName(), getShaderVersion()));
2474 if (function->hasPrototypeDeclaration() && mShaderVersion == 100)
Olli Etuaho5d653182016-01-04 14:43:28 +02002475 {
2476 // ESSL 1.00.17 section 4.2.7.
2477 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
2478 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02002479 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002480 function->setHasPrototypeDeclaration();
Olli Etuaho5d653182016-01-04 14:43:28 +02002481
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002482 TIntermFunctionPrototype *prototype =
2483 createPrototypeNodeFromFunction(*function, location, false);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002484
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002485 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002486
2487 if (!symbolTable.atGlobalLevel())
2488 {
2489 // ESSL 3.00.4 section 4.2.4.
2490 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002491 }
2492
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002493 return prototype;
2494}
2495
Olli Etuaho336b1472016-10-05 16:37:55 +01002496TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002497 TIntermFunctionPrototype *functionPrototype,
Olli Etuaho336b1472016-10-05 16:37:55 +01002498 TIntermBlock *functionBody,
2499 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002500{
Olli Etuahof51fdd22016-10-03 10:03:40 +01002501 // Check that non-void functions have at least one return statement.
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002502 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2503 {
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002504 error(location, "function does not return a value:",
2505 functionPrototype->getFunctionSymbolInfo()->getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002506 }
2507
Olli Etuahof51fdd22016-10-03 10:03:40 +01002508 if (functionBody == nullptr)
2509 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01002510 functionBody = new TIntermBlock();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002511 functionBody->setLine(location);
2512 }
Olli Etuaho336b1472016-10-05 16:37:55 +01002513 TIntermFunctionDefinition *functionNode =
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002514 new TIntermFunctionDefinition(functionPrototype, functionBody);
Olli Etuaho336b1472016-10-05 16:37:55 +01002515 functionNode->setLine(location);
Olli Etuahof51fdd22016-10-03 10:03:40 +01002516
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002517 symbolTable.pop();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002518 return functionNode;
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002519}
2520
Olli Etuaho476197f2016-10-11 13:59:08 +01002521void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
2522 TFunction **function,
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002523 TIntermFunctionPrototype **prototypeOut)
Jamie Madill185fb402015-06-12 15:48:48 -04002524{
Olli Etuaho476197f2016-10-11 13:59:08 +01002525 ASSERT(function);
2526 ASSERT(*function);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002527 const TSymbol *builtIn =
Olli Etuaho476197f2016-10-11 13:59:08 +01002528 symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002529
2530 if (builtIn)
2531 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002532 error(location, "built-in functions cannot be redefined", (*function)->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002533 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002534 else
Jamie Madill185fb402015-06-12 15:48:48 -04002535 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002536 TFunction *prevDec = static_cast<TFunction *>(
2537 symbolTable.find((*function)->getMangledName(), getShaderVersion()));
2538
2539 // Note: 'prevDec' could be 'function' if this is the first time we've seen function as it
2540 // would have just been put in the symbol table. Otherwise, we're looking up an earlier
2541 // occurance.
2542 if (*function != prevDec)
2543 {
2544 // Swap the parameters of the previous declaration to the parameters of the function
2545 // definition (parameter names may differ).
2546 prevDec->swapParameters(**function);
2547
2548 // The function definition will share the same symbol as any previous declaration.
2549 *function = prevDec;
2550 }
2551
2552 if ((*function)->isDefined())
2553 {
2554 error(location, "function already has a body", (*function)->getName().c_str());
2555 }
2556
2557 (*function)->setDefined();
Jamie Madill185fb402015-06-12 15:48:48 -04002558 }
Jamie Madill185fb402015-06-12 15:48:48 -04002559
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002560 // Remember the return type for later checking for return statements.
Olli Etuaho476197f2016-10-11 13:59:08 +01002561 mCurrentFunctionType = &((*function)->getReturnType());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002562 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002563
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002564 *prototypeOut = createPrototypeNodeFromFunction(**function, location, true);
Jamie Madill185fb402015-06-12 15:48:48 -04002565 setLoopNestingLevel(0);
2566}
2567
Jamie Madillb98c3a82015-07-23 14:26:04 -04002568TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002569{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002570 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002571 // We don't know at this point whether this is a function definition or a prototype.
2572 // The definition production code will check for redefinitions.
2573 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002574 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002575 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2576 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002577 //
2578 TFunction *prevDec =
2579 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302580
Martin Radevda6254b2016-12-14 17:00:36 +02002581 if (getShaderVersion() >= 300 &&
2582 symbolTable.hasUnmangledBuiltInForShaderVersion(function->getName().c_str(),
2583 getShaderVersion()))
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302584 {
Martin Radevda6254b2016-12-14 17:00:36 +02002585 // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions.
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302586 // Therefore overloading or redefining builtin functions is an error.
2587 error(location, "Name of a built-in function cannot be redeclared as function",
2588 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302589 }
2590 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002591 {
2592 if (prevDec->getReturnType() != function->getReturnType())
2593 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002594 error(location, "function must have the same return type in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002595 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002596 }
2597 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2598 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002599 if (prevDec->getParam(i).type->getQualifier() !=
2600 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002601 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002602 error(location,
2603 "function must have the same parameter qualifiers in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002604 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002605 }
2606 }
2607 }
2608
2609 //
2610 // Check for previously declared variables using the same name.
2611 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002612 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002613 if (prevSym)
2614 {
2615 if (!prevSym->isFunction())
2616 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002617 error(location, "redefinition of a function", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002618 }
2619 }
2620 else
2621 {
2622 // Insert the unmangled name to detect potential future redefinition as a variable.
Olli Etuaho476197f2016-10-11 13:59:08 +01002623 symbolTable.getOuterLevel()->insertUnmangled(function);
Jamie Madill185fb402015-06-12 15:48:48 -04002624 }
2625
2626 // We're at the inner scope level of the function's arguments and body statement.
2627 // Add the function prototype to the surrounding scope instead.
2628 symbolTable.getOuterLevel()->insert(function);
2629
Olli Etuaho78d13742017-01-18 13:06:10 +00002630 // Raise error message if main function takes any parameters or return anything other than void
2631 if (function->getName() == "main")
2632 {
2633 if (function->getParamCount() > 0)
2634 {
2635 error(location, "function cannot take any parameter(s)", "main");
2636 }
2637 if (function->getReturnType().getBasicType() != EbtVoid)
2638 {
2639 error(location, "main function cannot return a value",
2640 function->getReturnType().getBasicString());
2641 }
2642 }
2643
Jamie Madill185fb402015-06-12 15:48:48 -04002644 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002645 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2646 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002647 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2648 //
2649 return function;
2650}
2651
Olli Etuaho9de84a52016-06-14 17:36:01 +03002652TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2653 const TString *name,
2654 const TSourceLoc &location)
2655{
2656 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2657 {
2658 error(location, "no qualifiers allowed for function return",
2659 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002660 }
2661 if (!type.layoutQualifier.isEmpty())
2662 {
2663 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002664 }
jchen10cc2a10e2017-05-03 14:05:12 +08002665 // make sure an opaque type is not involved as well...
2666 std::string reason(getBasicString(type.getBasicType()));
2667 reason += "s can't be function return values";
2668 checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002669 if (mShaderVersion < 300)
2670 {
2671 // Array return values are forbidden, but there's also no valid syntax for declaring array
2672 // return values in ESSL 1.00.
Olli Etuaho77ba4082016-12-16 12:01:18 +00002673 ASSERT(type.arraySize == 0 || mDiagnostics->numErrors() > 0);
Olli Etuahoe29324f2016-06-15 10:58:03 +03002674
2675 if (type.isStructureContainingArrays())
2676 {
2677 // ESSL 1.00.17 section 6.1 Function Definitions
2678 error(location, "structures containing arrays can't be function return values",
2679 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002680 }
2681 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002682
2683 // Add the function as a prototype after parsing it (we do not support recursion)
2684 return new TFunction(name, new TType(type));
2685}
2686
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002687TFunction *TParseContext::addConstructorFunc(const TPublicType &publicType)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002688{
Martin Radev4a9cd802016-09-01 16:51:51 +03002689 if (publicType.isStructSpecifier())
Olli Etuahobd163f62015-11-13 12:15:38 +02002690 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002691 error(publicType.getLine(), "constructor can't be a structure definition",
2692 getBasicString(publicType.getBasicType()));
Olli Etuahobd163f62015-11-13 12:15:38 +02002693 }
2694
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002695 TType *type = new TType(publicType);
2696 if (!type->canBeConstructed())
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002697 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002698 error(publicType.getLine(), "cannot construct this type",
2699 getBasicString(publicType.getBasicType()));
2700 type->setBasicType(EbtFloat);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002701 }
2702
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002703 return new TFunction(nullptr, type, EOpConstruct);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002704}
2705
Jamie Madillb98c3a82015-07-23 14:26:04 -04002706// This function is used to test for the correctness of the parameters passed to various constructor
2707// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002708//
Olli Etuaho856c4972016-08-08 11:38:39 +03002709// 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 +00002710//
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002711TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00002712 TType type,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302713 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002714{
Olli Etuaho856c4972016-08-08 11:38:39 +03002715 if (type.isUnsizedArray())
2716 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002717 if (arguments->empty())
Olli Etuahobbe9fb52016-11-03 17:16:05 +00002718 {
2719 error(line, "implicitly sized array constructor must have at least one argument", "[]");
2720 type.setArraySize(1u);
2721 return TIntermTyped::CreateZero(type);
2722 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002723 type.setArraySize(static_cast<unsigned int>(arguments->size()));
Olli Etuaho856c4972016-08-08 11:38:39 +03002724 }
Olli Etuaho856c4972016-08-08 11:38:39 +03002725
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002726 if (!checkConstructorArguments(line, arguments, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002727 {
Olli Etuaho72d10202017-01-19 15:58:30 +00002728 return TIntermTyped::CreateZero(type);
Olli Etuaho856c4972016-08-08 11:38:39 +03002729 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002730
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002731 TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002732 constructorNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002733
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002734 TIntermTyped *constConstructor =
2735 intermediate.foldAggregateBuiltIn(constructorNode, mDiagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002736 if (constConstructor)
2737 {
2738 return constConstructor;
2739 }
2740
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002741 return constructorNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002742}
2743
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002744//
2745// Interface/uniform blocks
2746//
Olli Etuaho13389b62016-10-16 11:48:18 +01002747TIntermDeclaration *TParseContext::addInterfaceBlock(
Martin Radev70866b82016-07-22 15:27:42 +03002748 const TTypeQualifierBuilder &typeQualifierBuilder,
2749 const TSourceLoc &nameLine,
2750 const TString &blockName,
2751 TFieldList *fieldList,
2752 const TString *instanceName,
2753 const TSourceLoc &instanceLine,
2754 TIntermTyped *arrayIndex,
2755 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002756{
Olli Etuaho856c4972016-08-08 11:38:39 +03002757 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002758
Olli Etuaho77ba4082016-12-16 12:01:18 +00002759 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03002760
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002761 if (typeQualifier.qualifier != EvqUniform)
2762 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002763 error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform",
2764 getQualifierString(typeQualifier.qualifier));
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002765 }
2766
Martin Radev70866b82016-07-22 15:27:42 +03002767 if (typeQualifier.invariant)
2768 {
2769 error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
2770 }
2771
Olli Etuaho43364892017-02-13 16:00:12 +00002772 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
2773
2774 // TODO(oetuaho): Remove this and support binding for blocks.
2775 checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
Martin Radev2cc85b32016-08-05 16:22:53 +03002776
Andrei Volykhina5527072017-03-22 16:46:30 +03002777 checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
2778
Jamie Madill099c0f32013-06-20 11:55:52 -04002779 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03002780 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04002781
Jamie Madill099c0f32013-06-20 11:55:52 -04002782 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2783 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002784 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002785 }
2786
Jamie Madill1566ef72013-06-20 11:55:54 -04002787 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2788 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002789 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002790 }
2791
Olli Etuaho856c4972016-08-08 11:38:39 +03002792 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002793
Martin Radev2cc85b32016-08-05 16:22:53 +03002794 checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
2795
Arun Patole7e7e68d2015-05-22 12:02:25 +05302796 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2797 if (!symbolTable.declare(blockNameSymbol))
2798 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002799 error(nameLine, "redefinition of an interface block name", blockName.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002800 }
2801
Jamie Madill98493dd2013-07-08 14:39:03 -04002802 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302803 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2804 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002805 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302806 TType *fieldType = field->type();
jchen10cc2a10e2017-05-03 14:05:12 +08002807 if (IsOpaqueType(fieldType->getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +05302808 {
jchen10cc2a10e2017-05-03 14:05:12 +08002809 std::string reason("unsupported type - ");
2810 reason += fieldType->getBasicString();
2811 reason += " types are not allowed in interface blocks";
2812 error(field->line(), reason.c_str(), fieldType->getBasicString());
Martin Radev2cc85b32016-08-05 16:22:53 +03002813 }
2814
Jamie Madill98493dd2013-07-08 14:39:03 -04002815 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002816 switch (qualifier)
2817 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002818 case EvqGlobal:
2819 case EvqUniform:
2820 break;
2821 default:
2822 error(field->line(), "invalid qualifier on interface block member",
2823 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04002824 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002825 }
Jamie Madilla5efff92013-06-06 11:56:47 -04002826
Martin Radev70866b82016-07-22 15:27:42 +03002827 if (fieldType->isInvariant())
2828 {
2829 error(field->line(), "invalid qualifier on interface block member", "invariant");
2830 }
2831
Jamie Madilla5efff92013-06-06 11:56:47 -04002832 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04002833 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03002834 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Jamie Madill099c0f32013-06-20 11:55:52 -04002835
Jamie Madill98493dd2013-07-08 14:39:03 -04002836 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04002837 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002838 error(field->line(), "invalid layout qualifier: cannot be used here",
2839 getBlockStorageString(fieldLayoutQualifier.blockStorage));
Jamie Madill1566ef72013-06-20 11:55:54 -04002840 }
2841
Jamie Madill98493dd2013-07-08 14:39:03 -04002842 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04002843 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002844 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002845 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002846 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04002847 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002848 warning(field->line(),
2849 "extraneous layout qualifier: only has an effect on matrix types",
2850 getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
Jamie Madill099c0f32013-06-20 11:55:52 -04002851 }
2852
Jamie Madill98493dd2013-07-08 14:39:03 -04002853 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002854 }
2855
Jamie Madill98493dd2013-07-08 14:39:03 -04002856 // add array index
Olli Etuaho856c4972016-08-08 11:38:39 +03002857 unsigned int arraySize = 0;
2858 if (arrayIndex != nullptr)
Jamie Madill98493dd2013-07-08 14:39:03 -04002859 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002860 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
Jamie Madill98493dd2013-07-08 14:39:03 -04002861 }
2862
Jamie Madillb98c3a82015-07-23 14:26:04 -04002863 TInterfaceBlock *interfaceBlock =
2864 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2865 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
2866 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002867
2868 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04002869 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002870
Jamie Madill98493dd2013-07-08 14:39:03 -04002871 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002872 {
2873 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04002874 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2875 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002876 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302877 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04002878
2879 // set parent pointer of the field variable
2880 fieldType->setInterfaceBlock(interfaceBlock);
2881
Arun Patole7e7e68d2015-05-22 12:02:25 +05302882 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04002883 fieldVariable->setQualifier(typeQualifier.qualifier);
2884
Arun Patole7e7e68d2015-05-22 12:02:25 +05302885 if (!symbolTable.declare(fieldVariable))
2886 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002887 error(field->line(), "redefinition of an interface block member name",
2888 field->name().c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002889 }
2890 }
2891 }
2892 else
2893 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002894 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03002895
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002896 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05302897 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002898 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04002899
Arun Patole7e7e68d2015-05-22 12:02:25 +05302900 if (!symbolTable.declare(instanceTypeDef))
2901 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002902 error(instanceLine, "redefinition of an interface block instance name",
2903 instanceName->c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002904 }
2905
Jamie Madillb98c3a82015-07-23 14:26:04 -04002906 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002907 symbolName = instanceTypeDef->getName();
2908 }
2909
Olli Etuaho13389b62016-10-16 11:48:18 +01002910 TIntermSymbol *blockSymbol =
2911 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line);
2912 TIntermDeclaration *declaration = new TIntermDeclaration();
2913 declaration->appendDeclarator(blockSymbol);
2914 declaration->setLine(nameLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04002915
2916 exitStructDeclaration();
Olli Etuaho13389b62016-10-16 11:48:18 +01002917 return declaration;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002918}
2919
Olli Etuaho383b7912016-08-05 11:22:59 +03002920void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002921{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002922 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002923
2924 // Embedded structure definitions are not supported per GLSL ES spec.
Olli Etuaho4de340a2016-12-16 09:32:03 +00002925 // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302926 if (mStructNestingLevel > 1)
2927 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002928 error(line, "Embedded struct definitions are not allowed", "struct");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002929 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002930}
2931
2932void TParseContext::exitStructDeclaration()
2933{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002934 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002935}
2936
Olli Etuaho8a176262016-08-16 14:23:01 +03002937void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002938{
Jamie Madillacb4b812016-11-07 13:50:29 -05002939 if (!sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +05302940 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002941 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002942 }
2943
Arun Patole7e7e68d2015-05-22 12:02:25 +05302944 if (field.type()->getBasicType() != EbtStruct)
2945 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002946 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002947 }
2948
2949 // We're already inside a structure definition at this point, so add
2950 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302951 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2952 {
Jamie Madill41a49272014-03-18 16:10:13 -04002953 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002954 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
2955 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04002956 std::string reason = reasonStream.str();
Olli Etuaho4de340a2016-12-16 09:32:03 +00002957 error(line, reason.c_str(), field.name().c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03002958 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002959 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002960}
2961
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00002962//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002963// Parse an array index expression
2964//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002965TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
2966 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302967 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002968{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002969 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2970 {
2971 if (baseExpression->getAsSymbolNode())
2972 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302973 error(location, " left of '[' is not of type array, matrix, or vector ",
2974 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002975 }
2976 else
2977 {
2978 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2979 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002980
2981 TConstantUnion *unionArray = new TConstantUnion[1];
2982 unionArray->setFConst(0.0f);
2983 return intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst),
2984 location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002985 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002986
Jamie Madill21c1e452014-12-29 11:33:41 -05002987 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2988
Olli Etuaho36b05142015-11-12 13:10:42 +02002989 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
2990 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
2991 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
2992 // index is a constant expression.
2993 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
2994 {
2995 if (baseExpression->isInterfaceBlock())
2996 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002997 error(location,
2998 "array indexes for interface blocks arrays must be constant integral expressions",
2999 "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02003000 }
3001 else if (baseExpression->getQualifier() == EvqFragmentOut)
3002 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003003 error(location,
3004 "array indexes for fragment outputs must be constant integral expressions", "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02003005 }
Olli Etuaho3e960462015-11-12 15:58:39 +02003006 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
3007 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003008 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3e960462015-11-12 15:58:39 +02003009 }
Olli Etuaho36b05142015-11-12 13:10:42 +02003010 }
3011
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003012 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04003013 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003014 // If an out-of-range index is not qualified as constant, the behavior in the spec is
3015 // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
3016 // constant fold expressions that are not constant expressions). The most compatible way to
3017 // handle this case is to report a warning instead of an error and force the index to be in
3018 // the correct range.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003019 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003020 int index = indexConstantUnion->getIConst(0);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003021
3022 int safeIndex = -1;
3023
3024 if (baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04003025 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003026 if (baseExpression->getQualifier() == EvqFragData && index > 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003027 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003028 if (mShaderSpec == SH_WEBGL2_SPEC)
3029 {
3030 // Error has been already generated if index is not const.
3031 if (indexExpression->getQualifier() == EvqConst)
3032 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003033 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003034 }
3035 safeIndex = 0;
3036 }
3037 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
3038 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003039 outOfRangeError(outOfRangeIndexIsError, location,
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003040 "array index for gl_FragData must be zero when "
Olli Etuaho4de340a2016-12-16 09:32:03 +00003041 "GL_EXT_draw_buffers is disabled",
3042 "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003043 safeIndex = 0;
3044 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03003045 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003046 // Only do generic out-of-range check if similar error hasn't already been reported.
3047 if (safeIndex < 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003048 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003049 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3050 baseExpression->getArraySize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003051 "array index out of range");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003052 }
3053 }
3054 else if (baseExpression->isMatrix())
3055 {
3056 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
Olli Etuaho90892fb2016-07-14 14:44:51 +03003057 baseExpression->getType().getCols(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003058 "matrix field selection out of range");
Jamie Madill7164cf42013-07-08 13:30:59 -04003059 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003060 else if (baseExpression->isVector())
Jamie Madill7164cf42013-07-08 13:30:59 -04003061 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003062 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3063 baseExpression->getType().getNominalSize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003064 "vector field selection out of range");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003065 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003066
3067 ASSERT(safeIndex >= 0);
3068 // Data of constant unions can't be changed, because it may be shared with other
3069 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
3070 // sanitized object.
3071 if (safeIndex != index)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003072 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003073 TConstantUnion *safeConstantUnion = new TConstantUnion();
3074 safeConstantUnion->setIConst(safeIndex);
3075 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003076 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003077
3078 return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003079 mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003080 }
Jamie Madill7164cf42013-07-08 13:30:59 -04003081 else
3082 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003083 return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003084 mDiagnostics);
Jamie Madill7164cf42013-07-08 13:30:59 -04003085 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003086}
3087
Olli Etuaho90892fb2016-07-14 14:44:51 +03003088int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
3089 const TSourceLoc &location,
3090 int index,
3091 int arraySize,
Olli Etuaho4de340a2016-12-16 09:32:03 +00003092 const char *reason)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003093{
3094 if (index >= arraySize || index < 0)
3095 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003096 std::stringstream reasonStream;
3097 reasonStream << reason << " '" << index << "'";
3098 std::string token = reasonStream.str();
3099 outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
Olli Etuaho90892fb2016-07-14 14:44:51 +03003100 if (index < 0)
3101 {
3102 return 0;
3103 }
3104 else
3105 {
3106 return arraySize - 1;
3107 }
3108 }
3109 return index;
3110}
3111
Jamie Madillb98c3a82015-07-23 14:26:04 -04003112TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
3113 const TSourceLoc &dotLocation,
3114 const TString &fieldString,
3115 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003116{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003117 if (baseExpression->isArray())
3118 {
3119 error(fieldLocation, "cannot apply dot operator to an array", ".");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003120 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003121 }
3122
3123 if (baseExpression->isVector())
3124 {
3125 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003126 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
3127 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003128 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003129 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003130 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003131 }
3132
Olli Etuahob6fa0432016-09-28 16:28:05 +01003133 return TIntermediate::AddSwizzle(baseExpression, fields, dotLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003134 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003135 else if (baseExpression->getBasicType() == EbtStruct)
3136 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303137 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003138 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003139 {
3140 error(dotLocation, "structure has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003141 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003142 }
3143 else
3144 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003145 bool fieldFound = false;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003146 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003147 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003148 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003149 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003150 {
3151 fieldFound = true;
3152 break;
3153 }
3154 }
3155 if (fieldFound)
3156 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003157 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3158 index->setLine(fieldLocation);
3159 return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003160 dotLocation, mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003161 }
3162 else
3163 {
3164 error(dotLocation, " no such field in structure", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003165 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003166 }
3167 }
3168 }
Jamie Madill98493dd2013-07-08 14:39:03 -04003169 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003170 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303171 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003172 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003173 {
3174 error(dotLocation, "interface block has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003175 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003176 }
3177 else
3178 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003179 bool fieldFound = false;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003180 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003181 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003182 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003183 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003184 {
3185 fieldFound = true;
3186 break;
3187 }
3188 }
3189 if (fieldFound)
3190 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003191 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3192 index->setLine(fieldLocation);
3193 return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003194 dotLocation, mDiagnostics);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003195 }
3196 else
3197 {
3198 error(dotLocation, " no such field in interface block", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003199 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003200 }
3201 }
3202 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003203 else
3204 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003205 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003206 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03003207 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303208 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003209 }
3210 else
3211 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303212 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03003213 " field selection requires structure, vector, or interface block on left hand "
3214 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303215 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003216 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003217 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003218 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003219}
3220
Jamie Madillb98c3a82015-07-23 14:26:04 -04003221TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3222 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003223{
Martin Radev802abe02016-08-04 17:48:32 +03003224 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003225
3226 if (qualifierType == "shared")
3227 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003228 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003229 {
3230 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
3231 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003232 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003233 }
3234 else if (qualifierType == "packed")
3235 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003236 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003237 {
3238 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
3239 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003240 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003241 }
3242 else if (qualifierType == "std140")
3243 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003244 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003245 }
3246 else if (qualifierType == "row_major")
3247 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003248 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003249 }
3250 else if (qualifierType == "column_major")
3251 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003252 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003253 }
3254 else if (qualifierType == "location")
3255 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003256 error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
3257 qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003258 }
Andrei Volykhina5527072017-03-22 16:46:30 +03003259 else if (qualifierType == "yuv" && isExtensionEnabled("GL_EXT_YUV_target") &&
3260 mShaderType == GL_FRAGMENT_SHADER)
3261 {
3262 qualifier.yuv = true;
3263 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003264 else if (qualifierType == "rgba32f")
3265 {
3266 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3267 qualifier.imageInternalFormat = EiifRGBA32F;
3268 }
3269 else if (qualifierType == "rgba16f")
3270 {
3271 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3272 qualifier.imageInternalFormat = EiifRGBA16F;
3273 }
3274 else if (qualifierType == "r32f")
3275 {
3276 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3277 qualifier.imageInternalFormat = EiifR32F;
3278 }
3279 else if (qualifierType == "rgba8")
3280 {
3281 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3282 qualifier.imageInternalFormat = EiifRGBA8;
3283 }
3284 else if (qualifierType == "rgba8_snorm")
3285 {
3286 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3287 qualifier.imageInternalFormat = EiifRGBA8_SNORM;
3288 }
3289 else if (qualifierType == "rgba32i")
3290 {
3291 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3292 qualifier.imageInternalFormat = EiifRGBA32I;
3293 }
3294 else if (qualifierType == "rgba16i")
3295 {
3296 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3297 qualifier.imageInternalFormat = EiifRGBA16I;
3298 }
3299 else if (qualifierType == "rgba8i")
3300 {
3301 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3302 qualifier.imageInternalFormat = EiifRGBA8I;
3303 }
3304 else if (qualifierType == "r32i")
3305 {
3306 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3307 qualifier.imageInternalFormat = EiifR32I;
3308 }
3309 else if (qualifierType == "rgba32ui")
3310 {
3311 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3312 qualifier.imageInternalFormat = EiifRGBA32UI;
3313 }
3314 else if (qualifierType == "rgba16ui")
3315 {
3316 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3317 qualifier.imageInternalFormat = EiifRGBA16UI;
3318 }
3319 else if (qualifierType == "rgba8ui")
3320 {
3321 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3322 qualifier.imageInternalFormat = EiifRGBA8UI;
3323 }
3324 else if (qualifierType == "r32ui")
3325 {
3326 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3327 qualifier.imageInternalFormat = EiifR32UI;
3328 }
3329
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003330 else
3331 {
3332 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003333 }
3334
Jamie Madilla5efff92013-06-06 11:56:47 -04003335 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003336}
3337
Martin Radev802abe02016-08-04 17:48:32 +03003338void TParseContext::parseLocalSize(const TString &qualifierType,
3339 const TSourceLoc &qualifierTypeLine,
3340 int intValue,
3341 const TSourceLoc &intValueLine,
3342 const std::string &intValueString,
3343 size_t index,
Martin Radev4c4c8e72016-08-04 12:25:34 +03003344 sh::WorkGroupSize *localSize)
Martin Radev802abe02016-08-04 17:48:32 +03003345{
Olli Etuaho856c4972016-08-08 11:38:39 +03003346 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03003347 if (intValue < 1)
3348 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003349 std::stringstream reasonStream;
3350 reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
3351 std::string reason = reasonStream.str();
3352 error(intValueLine, reason.c_str(), intValueString.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003353 }
3354 (*localSize)[index] = intValue;
3355}
3356
Olli Etuaho09b04a22016-12-15 13:30:26 +00003357void TParseContext::parseNumViews(int intValue,
3358 const TSourceLoc &intValueLine,
3359 const std::string &intValueString,
3360 int *numViews)
3361{
3362 // This error is only specified in WebGL, but tightens unspecified behavior in the native
3363 // specification.
3364 if (intValue < 1)
3365 {
3366 error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
3367 }
3368 *numViews = intValue;
3369}
3370
Jamie Madillb98c3a82015-07-23 14:26:04 -04003371TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3372 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003373 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303374 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003375{
Martin Radev802abe02016-08-04 17:48:32 +03003376 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003377
Martin Radev802abe02016-08-04 17:48:32 +03003378 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003379
Martin Radev802abe02016-08-04 17:48:32 +03003380 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003381 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003382 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003383 if (intValue < 0)
3384 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003385 error(intValueLine, "out of range: location must be non-negative",
3386 intValueString.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003387 }
3388 else
3389 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003390 qualifier.location = intValue;
Olli Etuaho87d410c2016-09-05 13:33:26 +03003391 qualifier.locationsSpecified = 1;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003392 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003393 }
Olli Etuaho43364892017-02-13 16:00:12 +00003394 else if (qualifierType == "binding")
3395 {
3396 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3397 if (intValue < 0)
3398 {
3399 error(intValueLine, "out of range: binding must be non-negative",
3400 intValueString.c_str());
3401 }
3402 else
3403 {
3404 qualifier.binding = intValue;
3405 }
3406 }
Martin Radev802abe02016-08-04 17:48:32 +03003407 else if (qualifierType == "local_size_x")
3408 {
3409 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3410 &qualifier.localSize);
3411 }
3412 else if (qualifierType == "local_size_y")
3413 {
3414 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3415 &qualifier.localSize);
3416 }
3417 else if (qualifierType == "local_size_z")
3418 {
3419 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3420 &qualifier.localSize);
3421 }
Olli Etuaho95468d12017-05-04 11:14:34 +03003422 else if (qualifierType == "num_views" && isMultiviewExtensionEnabled() &&
Olli Etuaho09b04a22016-12-15 13:30:26 +00003423 mShaderType == GL_VERTEX_SHADER)
3424 {
3425 parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
3426 }
Martin Radev802abe02016-08-04 17:48:32 +03003427 else
3428 {
3429 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003430 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003431
Jamie Madilla5efff92013-06-06 11:56:47 -04003432 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003433}
3434
Olli Etuaho613b9592016-09-05 12:05:53 +03003435TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
3436{
3437 return new TTypeQualifierBuilder(
3438 new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
3439 mShaderVersion);
3440}
3441
Jamie Madillb98c3a82015-07-23 14:26:04 -04003442TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003443 TLayoutQualifier rightQualifier,
3444 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003445{
Martin Radevc28888b2016-07-22 15:27:42 +03003446 return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003447 mDiagnostics);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003448}
3449
Olli Etuaho4de340a2016-12-16 09:32:03 +00003450TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
3451 const TFieldList *newlyAddedFields,
3452 const TSourceLoc &location)
3453{
3454 for (TField *field : *newlyAddedFields)
3455 {
3456 for (TField *oldField : *processedFields)
3457 {
3458 if (oldField->name() == field->name())
3459 {
3460 error(location, "duplicate field name in structure", field->name().c_str());
3461 }
3462 }
3463 processedFields->push_back(field);
3464 }
3465 return processedFields;
3466}
3467
Martin Radev70866b82016-07-22 15:27:42 +03003468TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
3469 const TTypeQualifierBuilder &typeQualifierBuilder,
3470 TPublicType *typeSpecifier,
3471 TFieldList *fieldList)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003472{
Olli Etuaho77ba4082016-12-16 12:01:18 +00003473 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003474
Martin Radev70866b82016-07-22 15:27:42 +03003475 typeSpecifier->qualifier = typeQualifier.qualifier;
3476 typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03003477 typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03003478 typeSpecifier->invariant = typeQualifier.invariant;
3479 if (typeQualifier.precision != EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +05303480 {
Martin Radev70866b82016-07-22 15:27:42 +03003481 typeSpecifier->precision = typeQualifier.precision;
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003482 }
Martin Radev70866b82016-07-22 15:27:42 +03003483 return addStructDeclaratorList(*typeSpecifier, fieldList);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003484}
3485
Jamie Madillb98c3a82015-07-23 14:26:04 -04003486TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3487 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003488{
Martin Radev4a9cd802016-09-01 16:51:51 +03003489 checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
3490 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03003491
Martin Radev4a9cd802016-09-01 16:51:51 +03003492 checkIsNonVoid(typeSpecifier.getLine(), (*fieldList)[0]->name(), typeSpecifier.getBasicType());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003493
Martin Radev4a9cd802016-09-01 16:51:51 +03003494 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003495
Arun Patole7e7e68d2015-05-22 12:02:25 +05303496 for (unsigned int i = 0; i < fieldList->size(); ++i)
3497 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003498 //
3499 // Careful not to replace already known aspects of type, like array-ness
3500 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303501 TType *type = (*fieldList)[i]->type();
Martin Radev4a9cd802016-09-01 16:51:51 +03003502 type->setBasicType(typeSpecifier.getBasicType());
3503 type->setPrimarySize(typeSpecifier.getPrimarySize());
3504 type->setSecondarySize(typeSpecifier.getSecondarySize());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003505 type->setPrecision(typeSpecifier.precision);
3506 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003507 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
Martin Radev2cc85b32016-08-05 16:22:53 +03003508 type->setMemoryQualifier(typeSpecifier.memoryQualifier);
Martin Radev70866b82016-07-22 15:27:42 +03003509 type->setInvariant(typeSpecifier.invariant);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003510
3511 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303512 if (type->isArray())
3513 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003514 checkIsValidTypeForArray(typeSpecifier.getLine(), typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003515 }
3516 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003517 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Martin Radev4a9cd802016-09-01 16:51:51 +03003518 if (typeSpecifier.getUserDef())
Arun Patole7e7e68d2015-05-22 12:02:25 +05303519 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003520 type->setStruct(typeSpecifier.getUserDef()->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003521 }
3522
Martin Radev4a9cd802016-09-01 16:51:51 +03003523 checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003524 }
3525
Jamie Madill98493dd2013-07-08 14:39:03 -04003526 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003527}
3528
Martin Radev4a9cd802016-09-01 16:51:51 +03003529TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
3530 const TSourceLoc &nameLine,
3531 const TString *structName,
3532 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003533{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303534 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003535 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003536
Jamie Madill9b820842015-02-12 10:40:10 -05003537 // Store a bool in the struct if we're at global scope, to allow us to
3538 // skip the local struct scoping workaround in HLSL.
Jamie Madill9b820842015-02-12 10:40:10 -05003539 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003540
Jamie Madill98493dd2013-07-08 14:39:03 -04003541 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003542 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003543 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303544 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3545 if (!symbolTable.declare(userTypeDef))
3546 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003547 error(nameLine, "redefinition of a struct", structName->c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003548 }
3549 }
3550
3551 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003552 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003553 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003554 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003555 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003556 switch (qualifier)
3557 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003558 case EvqGlobal:
3559 case EvqTemporary:
3560 break;
3561 default:
3562 error(field.line(), "invalid qualifier on struct member",
3563 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003564 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003565 }
Martin Radev70866b82016-07-22 15:27:42 +03003566 if (field.type()->isInvariant())
3567 {
3568 error(field.line(), "invalid qualifier on struct member", "invariant");
3569 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003570 if (IsImage(field.type()->getBasicType()))
3571 {
3572 error(field.line(), "disallowed type in struct", field.type()->getBasicString());
3573 }
3574
Olli Etuaho43364892017-02-13 16:00:12 +00003575 checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
3576
3577 checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);
Martin Radev70866b82016-07-22 15:27:42 +03003578
3579 checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003580 }
3581
Martin Radev4a9cd802016-09-01 16:51:51 +03003582 TTypeSpecifierNonArray typeSpecifierNonArray;
3583 typeSpecifierNonArray.initialize(EbtStruct, structLine);
3584 typeSpecifierNonArray.userDef = structureType;
3585 typeSpecifierNonArray.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003586 exitStructDeclaration();
3587
Martin Radev4a9cd802016-09-01 16:51:51 +03003588 return typeSpecifierNonArray;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003589}
3590
Jamie Madillb98c3a82015-07-23 14:26:04 -04003591TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01003592 TIntermBlock *statementList,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003593 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003594{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003595 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003596 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003597 init->isVector())
3598 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003599 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3600 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003601 return nullptr;
3602 }
3603
Olli Etuahoac5274d2015-02-20 10:19:08 +02003604 if (statementList)
3605 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00003606 if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
Olli Etuahoac5274d2015-02-20 10:19:08 +02003607 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003608 return nullptr;
3609 }
3610 }
3611
Olli Etuahoa3a36662015-02-17 13:46:51 +02003612 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3613 if (node == nullptr)
3614 {
3615 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003616 return nullptr;
3617 }
3618 return node;
3619}
3620
3621TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3622{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003623 if (mSwitchNestingLevel == 0)
3624 {
3625 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003626 return nullptr;
3627 }
3628 if (condition == nullptr)
3629 {
3630 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003631 return nullptr;
3632 }
3633 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003634 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003635 {
3636 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003637 }
3638 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003639 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3640 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3641 // fold in case labels.
3642 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003643 {
3644 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003645 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003646 TIntermCase *node = intermediate.addCase(condition, loc);
3647 if (node == nullptr)
3648 {
3649 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003650 return nullptr;
3651 }
3652 return node;
3653}
3654
3655TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3656{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003657 if (mSwitchNestingLevel == 0)
3658 {
3659 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003660 return nullptr;
3661 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003662 TIntermCase *node = intermediate.addCase(nullptr, loc);
3663 if (node == nullptr)
3664 {
3665 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003666 return nullptr;
3667 }
3668 return node;
3669}
3670
Jamie Madillb98c3a82015-07-23 14:26:04 -04003671TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3672 TIntermTyped *child,
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003673 const TSourceLoc &loc)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003674{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003675 ASSERT(child != nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003676
3677 switch (op)
3678 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003679 case EOpLogicalNot:
3680 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3681 child->isVector())
3682 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003683 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003684 return nullptr;
3685 }
3686 break;
3687 case EOpBitwiseNot:
3688 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3689 child->isMatrix() || child->isArray())
3690 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003691 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003692 return nullptr;
3693 }
3694 break;
3695 case EOpPostIncrement:
3696 case EOpPreIncrement:
3697 case EOpPostDecrement:
3698 case EOpPreDecrement:
3699 case EOpNegative:
3700 case EOpPositive:
Olli Etuaho94050052017-05-08 14:17:44 +03003701 if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() ||
3702 child->getBasicType() == EbtBool || child->isArray() ||
3703 IsOpaqueType(child->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -04003704 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003705 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003706 return nullptr;
3707 }
3708 // Operators for built-ins are already type checked against their prototype.
3709 default:
3710 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003711 }
3712
Olli Etuahof119a262016-08-19 15:54:22 +03003713 TIntermUnary *node = new TIntermUnary(op, child);
3714 node->setLine(loc);
Olli Etuahof119a262016-08-19 15:54:22 +03003715
Olli Etuaho77ba4082016-12-16 12:01:18 +00003716 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuahof119a262016-08-19 15:54:22 +03003717 if (foldedNode)
3718 return foldedNode;
3719
3720 return node;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003721}
3722
Olli Etuaho09b22472015-02-11 11:47:26 +02003723TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3724{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003725 TIntermTyped *node = createUnaryMath(op, child, loc);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003726 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003727 {
Olli Etuaho09b22472015-02-11 11:47:26 +02003728 return child;
3729 }
3730 return node;
3731}
3732
Jamie Madillb98c3a82015-07-23 14:26:04 -04003733TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3734 TIntermTyped *child,
3735 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003736{
Olli Etuaho856c4972016-08-08 11:38:39 +03003737 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003738 return addUnaryMath(op, child, loc);
3739}
3740
Jamie Madillb98c3a82015-07-23 14:26:04 -04003741bool TParseContext::binaryOpCommonCheck(TOperator op,
3742 TIntermTyped *left,
3743 TIntermTyped *right,
3744 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003745{
jchen10b4cf5652017-05-05 18:51:17 +08003746 // Check opaque types are not allowed to be operands in expressions other than array indexing
3747 // and structure member selection.
3748 if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType()))
3749 {
3750 switch (op)
3751 {
3752 case EOpIndexDirect:
3753 case EOpIndexIndirect:
3754 break;
3755 case EOpIndexDirectStruct:
3756 UNREACHABLE();
3757
3758 default:
3759 error(loc, "Invalid operation for variables with an opaque type",
3760 GetOperatorString(op));
3761 return false;
3762 }
3763 }
jchen10cc2a10e2017-05-03 14:05:12 +08003764
Olli Etuaho244be012016-08-18 15:26:02 +03003765 if (left->getType().getStruct() || right->getType().getStruct())
3766 {
3767 switch (op)
3768 {
3769 case EOpIndexDirectStruct:
3770 ASSERT(left->getType().getStruct());
3771 break;
3772 case EOpEqual:
3773 case EOpNotEqual:
3774 case EOpAssign:
3775 case EOpInitialize:
3776 if (left->getType() != right->getType())
3777 {
3778 return false;
3779 }
3780 break;
3781 default:
3782 error(loc, "Invalid operation for structs", GetOperatorString(op));
3783 return false;
3784 }
3785 }
3786
Olli Etuaho94050052017-05-08 14:17:44 +03003787 if (left->isInterfaceBlock() || right->isInterfaceBlock())
3788 {
3789 switch (op)
3790 {
3791 case EOpIndexDirectInterfaceBlock:
3792 ASSERT(left->getType().getInterfaceBlock());
3793 break;
3794 default:
3795 error(loc, "Invalid operation for interface blocks", GetOperatorString(op));
3796 return false;
3797 }
3798 }
3799
Olli Etuahod6b14282015-03-17 14:31:35 +02003800 if (left->isArray() || right->isArray())
3801 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003802 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003803 {
3804 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3805 return false;
3806 }
3807
3808 if (left->isArray() != right->isArray())
3809 {
3810 error(loc, "array / non-array mismatch", GetOperatorString(op));
3811 return false;
3812 }
3813
3814 switch (op)
3815 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003816 case EOpEqual:
3817 case EOpNotEqual:
3818 case EOpAssign:
3819 case EOpInitialize:
3820 break;
3821 default:
3822 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3823 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02003824 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03003825 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02003826 if (left->getArraySize() != right->getArraySize())
3827 {
3828 error(loc, "array size mismatch", GetOperatorString(op));
3829 return false;
3830 }
Olli Etuahod6b14282015-03-17 14:31:35 +02003831 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003832
3833 // Check ops which require integer / ivec parameters
3834 bool isBitShift = false;
3835 switch (op)
3836 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003837 case EOpBitShiftLeft:
3838 case EOpBitShiftRight:
3839 case EOpBitShiftLeftAssign:
3840 case EOpBitShiftRightAssign:
3841 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3842 // check that the basic type is an integer type.
3843 isBitShift = true;
3844 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3845 {
3846 return false;
3847 }
3848 break;
3849 case EOpBitwiseAnd:
3850 case EOpBitwiseXor:
3851 case EOpBitwiseOr:
3852 case EOpBitwiseAndAssign:
3853 case EOpBitwiseXorAssign:
3854 case EOpBitwiseOrAssign:
3855 // It is enough to check the type of only one operand, since later it
3856 // is checked that the operand types match.
3857 if (!IsInteger(left->getBasicType()))
3858 {
3859 return false;
3860 }
3861 break;
3862 default:
3863 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003864 }
3865
3866 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3867 // So the basic type should usually match.
3868 if (!isBitShift && left->getBasicType() != right->getBasicType())
3869 {
3870 return false;
3871 }
3872
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003873 // Check that:
3874 // 1. Type sizes match exactly on ops that require that.
3875 // 2. Restrictions for structs that contain arrays or samplers are respected.
3876 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
Jamie Madillb98c3a82015-07-23 14:26:04 -04003877 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003878 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003879 case EOpAssign:
3880 case EOpInitialize:
3881 case EOpEqual:
3882 case EOpNotEqual:
3883 // ESSL 1.00 sections 5.7, 5.8, 5.9
3884 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
3885 {
3886 error(loc, "undefined operation for structs containing arrays",
3887 GetOperatorString(op));
3888 return false;
3889 }
3890 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3891 // we interpret the spec so that this extends to structs containing samplers,
3892 // similarly to ESSL 1.00 spec.
3893 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
3894 left->getType().isStructureContainingSamplers())
3895 {
3896 error(loc, "undefined operation for structs containing samplers",
3897 GetOperatorString(op));
3898 return false;
3899 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003900
Olli Etuahoe1805592017-01-02 16:41:20 +00003901 if ((left->getNominalSize() != right->getNominalSize()) ||
3902 (left->getSecondarySize() != right->getSecondarySize()))
3903 {
3904 error(loc, "dimension mismatch", GetOperatorString(op));
3905 return false;
3906 }
3907 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003908 case EOpLessThan:
3909 case EOpGreaterThan:
3910 case EOpLessThanEqual:
3911 case EOpGreaterThanEqual:
Olli Etuahoe1805592017-01-02 16:41:20 +00003912 if (!left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04003913 {
Olli Etuahoe1805592017-01-02 16:41:20 +00003914 error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003915 return false;
3916 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003917 break;
3918 case EOpAdd:
3919 case EOpSub:
3920 case EOpDiv:
3921 case EOpIMod:
3922 case EOpBitShiftLeft:
3923 case EOpBitShiftRight:
3924 case EOpBitwiseAnd:
3925 case EOpBitwiseXor:
3926 case EOpBitwiseOr:
3927 case EOpAddAssign:
3928 case EOpSubAssign:
3929 case EOpDivAssign:
3930 case EOpIModAssign:
3931 case EOpBitShiftLeftAssign:
3932 case EOpBitShiftRightAssign:
3933 case EOpBitwiseAndAssign:
3934 case EOpBitwiseXorAssign:
3935 case EOpBitwiseOrAssign:
3936 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
3937 {
3938 return false;
3939 }
3940
3941 // Are the sizes compatible?
3942 if (left->getNominalSize() != right->getNominalSize() ||
3943 left->getSecondarySize() != right->getSecondarySize())
3944 {
3945 // If the nominal sizes of operands do not match:
3946 // One of them must be a scalar.
3947 if (!left->isScalar() && !right->isScalar())
3948 return false;
3949
3950 // In the case of compound assignment other than multiply-assign,
3951 // the right side needs to be a scalar. Otherwise a vector/matrix
3952 // would be assigned to a scalar. A scalar can't be shifted by a
3953 // vector either.
3954 if (!right->isScalar() &&
3955 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
3956 return false;
3957 }
3958 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003959 default:
3960 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003961 }
3962
Olli Etuahod6b14282015-03-17 14:31:35 +02003963 return true;
3964}
3965
Olli Etuaho1dded802016-08-18 18:13:13 +03003966bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
3967 const TType &left,
3968 const TType &right)
3969{
3970 switch (op)
3971 {
3972 case EOpMul:
3973 case EOpMulAssign:
3974 return left.getNominalSize() == right.getNominalSize() &&
3975 left.getSecondarySize() == right.getSecondarySize();
3976 case EOpVectorTimesScalar:
3977 return true;
3978 case EOpVectorTimesScalarAssign:
3979 ASSERT(!left.isMatrix() && !right.isMatrix());
3980 return left.isVector() && !right.isVector();
3981 case EOpVectorTimesMatrix:
3982 return left.getNominalSize() == right.getRows();
3983 case EOpVectorTimesMatrixAssign:
3984 ASSERT(!left.isMatrix() && right.isMatrix());
3985 return left.isVector() && left.getNominalSize() == right.getRows() &&
3986 left.getNominalSize() == right.getCols();
3987 case EOpMatrixTimesVector:
3988 return left.getCols() == right.getNominalSize();
3989 case EOpMatrixTimesScalar:
3990 return true;
3991 case EOpMatrixTimesScalarAssign:
3992 ASSERT(left.isMatrix() && !right.isMatrix());
3993 return !right.isVector();
3994 case EOpMatrixTimesMatrix:
3995 return left.getCols() == right.getRows();
3996 case EOpMatrixTimesMatrixAssign:
3997 ASSERT(left.isMatrix() && right.isMatrix());
3998 // We need to check two things:
3999 // 1. The matrix multiplication step is valid.
4000 // 2. The result will have the same number of columns as the lvalue.
4001 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
4002
4003 default:
4004 UNREACHABLE();
4005 return false;
4006 }
4007}
4008
Jamie Madillb98c3a82015-07-23 14:26:04 -04004009TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
4010 TIntermTyped *left,
4011 TIntermTyped *right,
4012 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02004013{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004014 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004015 return nullptr;
4016
Olli Etuahofc1806e2015-03-17 13:03:11 +02004017 switch (op)
4018 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004019 case EOpEqual:
4020 case EOpNotEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04004021 case EOpLessThan:
4022 case EOpGreaterThan:
4023 case EOpLessThanEqual:
4024 case EOpGreaterThanEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04004025 break;
4026 case EOpLogicalOr:
4027 case EOpLogicalXor:
4028 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03004029 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4030 !right->getType().getStruct());
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00004031 if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04004032 {
4033 return nullptr;
4034 }
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00004035 // Basic types matching should have been already checked.
4036 ASSERT(right->getBasicType() == EbtBool);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004037 break;
4038 case EOpAdd:
4039 case EOpSub:
4040 case EOpDiv:
4041 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03004042 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4043 !right->getType().getStruct());
4044 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04004045 {
4046 return nullptr;
4047 }
4048 break;
4049 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03004050 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4051 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004052 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03004053 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04004054 {
4055 return nullptr;
4056 }
4057 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004058 default:
4059 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02004060 }
4061
Olli Etuaho1dded802016-08-18 18:13:13 +03004062 if (op == EOpMul)
4063 {
4064 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
4065 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4066 {
4067 return nullptr;
4068 }
4069 }
4070
Olli Etuaho3fdec912016-08-18 15:08:06 +03004071 TIntermBinary *node = new TIntermBinary(op, left, right);
4072 node->setLine(loc);
4073
Olli Etuaho3fdec912016-08-18 15:08:06 +03004074 // See if we can fold constants.
Olli Etuaho77ba4082016-12-16 12:01:18 +00004075 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuaho3fdec912016-08-18 15:08:06 +03004076 if (foldedNode)
4077 return foldedNode;
4078
4079 return node;
Olli Etuahofc1806e2015-03-17 13:03:11 +02004080}
4081
Jamie Madillb98c3a82015-07-23 14:26:04 -04004082TIntermTyped *TParseContext::addBinaryMath(TOperator op,
4083 TIntermTyped *left,
4084 TIntermTyped *right,
4085 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004086{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004087 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004088 if (node == 0)
4089 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004090 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4091 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02004092 return left;
4093 }
4094 return node;
4095}
4096
Jamie Madillb98c3a82015-07-23 14:26:04 -04004097TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
4098 TIntermTyped *left,
4099 TIntermTyped *right,
4100 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004101{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004102 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004103 if (node == 0)
4104 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004105 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4106 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04004107 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02004108 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004109 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
4110 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004111 }
4112 return node;
4113}
4114
Olli Etuaho13389b62016-10-16 11:48:18 +01004115TIntermBinary *TParseContext::createAssign(TOperator op,
4116 TIntermTyped *left,
4117 TIntermTyped *right,
4118 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004119{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004120 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004121 {
Olli Etuaho1dded802016-08-18 18:13:13 +03004122 if (op == EOpMulAssign)
4123 {
4124 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
4125 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4126 {
4127 return nullptr;
4128 }
4129 }
Olli Etuaho3fdec912016-08-18 15:08:06 +03004130 TIntermBinary *node = new TIntermBinary(op, left, right);
4131 node->setLine(loc);
4132
Olli Etuaho3fdec912016-08-18 15:08:06 +03004133 return node;
Olli Etuahod6b14282015-03-17 14:31:35 +02004134 }
4135 return nullptr;
4136}
4137
Jamie Madillb98c3a82015-07-23 14:26:04 -04004138TIntermTyped *TParseContext::addAssign(TOperator op,
4139 TIntermTyped *left,
4140 TIntermTyped *right,
4141 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004142{
4143 TIntermTyped *node = createAssign(op, left, right, loc);
4144 if (node == nullptr)
4145 {
4146 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02004147 return left;
4148 }
4149 return node;
4150}
4151
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004152TIntermTyped *TParseContext::addComma(TIntermTyped *left,
4153 TIntermTyped *right,
4154 const TSourceLoc &loc)
4155{
Corentin Wallez0d959252016-07-12 17:26:32 -04004156 // WebGL2 section 5.26, the following results in an error:
4157 // "Sequence operator applied to void, arrays, or structs containing arrays"
Jamie Madilld7b1ab52016-12-12 14:42:19 -05004158 if (mShaderSpec == SH_WEBGL2_SPEC &&
4159 (left->isArray() || left->getBasicType() == EbtVoid ||
4160 left->getType().isStructureContainingArrays() || right->isArray() ||
4161 right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
Corentin Wallez0d959252016-07-12 17:26:32 -04004162 {
4163 error(loc,
4164 "sequence operator is not allowed for void, arrays, or structs containing arrays",
4165 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04004166 }
4167
Olli Etuaho4db7ded2016-10-13 12:23:11 +01004168 return TIntermediate::AddComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004169}
4170
Olli Etuaho49300862015-02-20 14:54:49 +02004171TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
4172{
4173 switch (op)
4174 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004175 case EOpContinue:
4176 if (mLoopNestingLevel <= 0)
4177 {
4178 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004179 }
4180 break;
4181 case EOpBreak:
4182 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
4183 {
4184 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004185 }
4186 break;
4187 case EOpReturn:
4188 if (mCurrentFunctionType->getBasicType() != EbtVoid)
4189 {
4190 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004191 }
4192 break;
4193 default:
4194 // No checks for discard
4195 break;
Olli Etuaho49300862015-02-20 14:54:49 +02004196 }
4197 return intermediate.addBranch(op, loc);
4198}
4199
Jamie Madillb98c3a82015-07-23 14:26:04 -04004200TIntermBranch *TParseContext::addBranch(TOperator op,
4201 TIntermTyped *returnValue,
4202 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02004203{
4204 ASSERT(op == EOpReturn);
4205 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004206 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02004207 {
4208 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004209 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004210 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02004211 {
4212 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004213 }
4214 return intermediate.addBranch(op, returnValue, loc);
4215}
4216
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004217void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
4218{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004219 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Olli Etuahobd674552016-10-06 13:28:42 +01004220 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004221 TIntermNode *offset = nullptr;
4222 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuahoec9232b2017-03-27 17:01:37 +03004223 if (name == "texelFetchOffset" || name == "textureLodOffset" ||
4224 name == "textureProjLodOffset" || name == "textureGradOffset" ||
4225 name == "textureProjGradOffset")
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004226 {
4227 offset = arguments->back();
4228 }
Olli Etuahoec9232b2017-03-27 17:01:37 +03004229 else if (name == "textureOffset" || name == "textureProjOffset")
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004230 {
4231 // A bias parameter might follow the offset parameter.
4232 ASSERT(arguments->size() >= 3);
4233 offset = (*arguments)[2];
4234 }
4235 if (offset != nullptr)
4236 {
4237 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
4238 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
4239 {
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004240 error(functionCall->getLine(), "Texture offset must be a constant expression",
Olli Etuahoec9232b2017-03-27 17:01:37 +03004241 name.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004242 }
4243 else
4244 {
4245 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
4246 size_t size = offsetConstantUnion->getType().getObjectSize();
4247 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
4248 for (size_t i = 0u; i < size; ++i)
4249 {
4250 int offsetValue = values[i].getIConst();
4251 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
4252 {
4253 std::stringstream tokenStream;
4254 tokenStream << offsetValue;
4255 std::string token = tokenStream.str();
4256 error(offset->getLine(), "Texture offset value out of valid range",
4257 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004258 }
4259 }
4260 }
4261 }
4262}
4263
Martin Radev2cc85b32016-08-05 16:22:53 +03004264// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
4265void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
4266{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004267 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Martin Radev2cc85b32016-08-05 16:22:53 +03004268 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
4269
4270 if (name.compare(0, 5, "image") == 0)
4271 {
4272 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuaho485eefd2017-02-14 17:40:06 +00004273 TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
Martin Radev2cc85b32016-08-05 16:22:53 +03004274
Olli Etuaho485eefd2017-02-14 17:40:06 +00004275 const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
Martin Radev2cc85b32016-08-05 16:22:53 +03004276
4277 if (name.compare(5, 5, "Store") == 0)
4278 {
4279 if (memoryQualifier.readonly)
4280 {
4281 error(imageNode->getLine(),
4282 "'imageStore' cannot be used with images qualified as 'readonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004283 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03004284 }
4285 }
4286 else if (name.compare(5, 4, "Load") == 0)
4287 {
4288 if (memoryQualifier.writeonly)
4289 {
4290 error(imageNode->getLine(),
4291 "'imageLoad' cannot be used with images qualified as 'writeonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004292 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03004293 }
4294 }
4295 }
4296}
4297
4298// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
4299void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
4300 const TFunction *functionDefinition,
4301 const TIntermAggregate *functionCall)
4302{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004303 ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
Martin Radev2cc85b32016-08-05 16:22:53 +03004304
4305 const TIntermSequence &arguments = *functionCall->getSequence();
4306
4307 ASSERT(functionDefinition->getParamCount() == arguments.size());
4308
4309 for (size_t i = 0; i < arguments.size(); ++i)
4310 {
Olli Etuaho485eefd2017-02-14 17:40:06 +00004311 TIntermTyped *typedArgument = arguments[i]->getAsTyped();
4312 const TType &functionArgumentType = typedArgument->getType();
Martin Radev2cc85b32016-08-05 16:22:53 +03004313 const TType &functionParameterType = *functionDefinition->getParam(i).type;
4314 ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
4315
4316 if (IsImage(functionArgumentType.getBasicType()))
4317 {
4318 const TMemoryQualifier &functionArgumentMemoryQualifier =
4319 functionArgumentType.getMemoryQualifier();
4320 const TMemoryQualifier &functionParameterMemoryQualifier =
4321 functionParameterType.getMemoryQualifier();
4322 if (functionArgumentMemoryQualifier.readonly &&
4323 !functionParameterMemoryQualifier.readonly)
4324 {
4325 error(functionCall->getLine(),
4326 "Function call discards the 'readonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004327 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03004328 }
4329
4330 if (functionArgumentMemoryQualifier.writeonly &&
4331 !functionParameterMemoryQualifier.writeonly)
4332 {
4333 error(functionCall->getLine(),
4334 "Function call discards the 'writeonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004335 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03004336 }
Martin Radev049edfa2016-11-11 14:35:37 +02004337
4338 if (functionArgumentMemoryQualifier.coherent &&
4339 !functionParameterMemoryQualifier.coherent)
4340 {
4341 error(functionCall->getLine(),
4342 "Function call discards the 'coherent' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004343 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02004344 }
4345
4346 if (functionArgumentMemoryQualifier.volatileQualifier &&
4347 !functionParameterMemoryQualifier.volatileQualifier)
4348 {
4349 error(functionCall->getLine(),
4350 "Function call discards the 'volatile' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004351 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02004352 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004353 }
4354 }
4355}
4356
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004357TIntermSequence *TParseContext::createEmptyArgumentsList()
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004358{
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004359 return new TIntermSequence();
Olli Etuaho72d10202017-01-19 15:58:30 +00004360}
4361
4362TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004363 TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00004364 TIntermNode *thisNode,
4365 const TSourceLoc &loc)
4366{
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004367 if (thisNode != nullptr)
4368 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004369 return addMethod(fnCall, arguments, thisNode, loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004370 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004371
4372 TOperator op = fnCall->getBuiltInOp();
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004373 if (op == EOpConstruct)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004374 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004375 return addConstructor(arguments, fnCall->getReturnType(), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004376 }
4377 else
4378 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004379 ASSERT(op == EOpNull);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004380 return addNonConstructorFunctionCall(fnCall, arguments, loc);
4381 }
4382}
4383
4384TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
4385 TIntermSequence *arguments,
4386 TIntermNode *thisNode,
4387 const TSourceLoc &loc)
4388{
4389 TConstantUnion *unionArray = new TConstantUnion[1];
4390 int arraySize = 0;
4391 TIntermTyped *typedThis = thisNode->getAsTyped();
4392 // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
4393 // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
4394 // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
4395 // So accessing fnCall->getName() below is safe.
4396 if (fnCall->getName() != "length")
4397 {
4398 error(loc, "invalid method", fnCall->getName().c_str());
4399 }
4400 else if (!arguments->empty())
4401 {
4402 error(loc, "method takes no parameters", "length");
4403 }
4404 else if (typedThis == nullptr || !typedThis->isArray())
4405 {
4406 error(loc, "length can only be called on arrays", "length");
4407 }
4408 else
4409 {
4410 arraySize = typedThis->getArraySize();
4411 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuaho72d10202017-01-19 15:58:30 +00004412 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004413 // This code path can be hit with expressions like these:
4414 // (a = b).length()
4415 // (func()).length()
4416 // (int[3](0, 1, 2)).length()
4417 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
4418 // expression.
4419 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
4420 // spec section 5.9 which allows "An array, vector or matrix expression with the
4421 // length method applied".
4422 error(loc, "length can only be called on array names, not on array expressions",
4423 "length");
Olli Etuaho72d10202017-01-19 15:58:30 +00004424 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004425 }
4426 unionArray->setIConst(arraySize);
4427 return intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
4428}
4429
4430TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
4431 TIntermSequence *arguments,
4432 const TSourceLoc &loc)
4433{
4434 // First find by unmangled name to check whether the function name has been
4435 // hidden by a variable name or struct typename.
4436 // If a function is found, check for one with a matching argument list.
4437 bool builtIn;
4438 const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn);
4439 if (symbol != nullptr && !symbol->isFunction())
4440 {
4441 error(loc, "function name expected", fnCall->getName().c_str());
4442 }
4443 else
4444 {
4445 symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments),
4446 mShaderVersion, &builtIn);
4447 if (symbol == nullptr)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004448 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004449 error(loc, "no matching overloaded function found", fnCall->getName().c_str());
4450 }
4451 else
4452 {
4453 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004454 //
4455 // A declared function.
4456 //
Olli Etuaho383b7912016-08-05 11:22:59 +03004457 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004458 {
Olli Etuaho856c4972016-08-08 11:38:39 +03004459 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004460 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004461 TOperator op = fnCandidate->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004462 if (builtIn && op != EOpNull)
4463 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004464 // A function call mapped to a built-in operation.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004465 if (fnCandidate->getParamCount() == 1)
4466 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004467 // Treat it like a built-in unary operator.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004468 TIntermNode *unaryParamNode = arguments->front();
4469 TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004470 ASSERT(callNode != nullptr);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004471 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004472 }
4473 else
4474 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004475 TIntermAggregate *callNode =
Olli Etuahofe486322017-03-21 09:30:54 +00004476 TIntermAggregate::Create(fnCandidate->getReturnType(), op, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004477 callNode->setLine(loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004478
4479 // Some built-in functions have out parameters too.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004480 functionCallLValueErrorCheck(fnCandidate, callNode);
Arun Patole274f0702015-05-05 13:33:30 +05304481
Olli Etuaho7c3848e2015-11-04 13:19:17 +02004482 // See if we can constant fold a built-in. Note that this may be possible even
4483 // if it is not const-qualified.
Olli Etuahof119a262016-08-19 15:54:22 +03004484 TIntermTyped *foldedNode =
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004485 intermediate.foldAggregateBuiltIn(callNode, mDiagnostics);
Arun Patole274f0702015-05-05 13:33:30 +05304486 if (foldedNode)
4487 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004488 return foldedNode;
Arun Patole274f0702015-05-05 13:33:30 +05304489 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004490 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004491 }
4492 }
4493 else
4494 {
4495 // This is a real function call
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004496 TIntermAggregate *callNode = nullptr;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004497
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004498 // If builtIn == false, the function is user defined - could be an overloaded
4499 // built-in as well.
4500 // if builtIn == true, it's a builtIn function with no op associated with it.
4501 // This needs to happen after the function info including name is set.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004502 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004503 {
Olli Etuahofe486322017-03-21 09:30:54 +00004504 callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004505 checkTextureOffsetConst(callNode);
4506 checkImageMemoryAccessForBuiltinFunctions(callNode);
Martin Radev2cc85b32016-08-05 16:22:53 +03004507 }
4508 else
4509 {
Olli Etuahofe486322017-03-21 09:30:54 +00004510 callNode = TIntermAggregate::CreateFunctionCall(*fnCandidate, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004511 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004512 }
4513
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004514 functionCallLValueErrorCheck(fnCandidate, callNode);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004515
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004516 callNode->setLine(loc);
4517
4518 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004519 }
4520 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004521 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004522
4523 // Error message was already written. Put on a dummy node for error recovery.
4524 return TIntermTyped::CreateZero(TType(EbtFloat, EbpMedium, EvqConst));
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004525}
4526
Jamie Madillb98c3a82015-07-23 14:26:04 -04004527TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004528 TIntermTyped *trueExpression,
4529 TIntermTyped *falseExpression,
Olli Etuaho52901742015-04-15 13:42:45 +03004530 const TSourceLoc &loc)
4531{
Olli Etuaho856c4972016-08-08 11:38:39 +03004532 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03004533
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004534 if (trueExpression->getType() != falseExpression->getType())
Olli Etuaho52901742015-04-15 13:42:45 +03004535 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004536 binaryOpError(loc, "?:", trueExpression->getCompleteString(),
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004537 falseExpression->getCompleteString());
4538 return falseExpression;
Olli Etuaho52901742015-04-15 13:42:45 +03004539 }
Olli Etuahode318b22016-10-25 16:18:25 +01004540 if (IsOpaqueType(trueExpression->getBasicType()))
4541 {
4542 // ESSL 1.00 section 4.1.7
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004543 // ESSL 3.00.6 section 4.1.7
Olli Etuahode318b22016-10-25 16:18:25 +01004544 // Opaque/sampler types are not allowed in most types of expressions, including ternary.
4545 // Note that structs containing opaque types don't need to be checked as structs are
4546 // forbidden below.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004547 error(loc, "ternary operator is not allowed for opaque types", "?:");
Olli Etuahode318b22016-10-25 16:18:25 +01004548 return falseExpression;
4549 }
4550
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004551 // ESSL 1.00.17 sections 5.2 and 5.7:
Olli Etuahoa2d53032015-04-15 14:14:44 +03004552 // Ternary operator is not among the operators allowed for structures/arrays.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004553 // ESSL 3.00.6 section 5.7:
4554 // Ternary operator support is optional for arrays. No certainty that it works across all
4555 // devices with struct either, so we err on the side of caution here. TODO (oetuaho@nvidia.com):
4556 // Would be nice to make the spec and implementation agree completely here.
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004557 if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
Olli Etuahoa2d53032015-04-15 14:14:44 +03004558 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004559 error(loc, "ternary operator is not allowed for structures or arrays", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004560 return falseExpression;
Olli Etuahoa2d53032015-04-15 14:14:44 +03004561 }
Olli Etuaho94050052017-05-08 14:17:44 +03004562 if (trueExpression->getBasicType() == EbtInterfaceBlock)
4563 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004564 error(loc, "ternary operator is not allowed for interface blocks", "?:");
Olli Etuaho94050052017-05-08 14:17:44 +03004565 return falseExpression;
4566 }
4567
Corentin Wallez0d959252016-07-12 17:26:32 -04004568 // WebGL2 section 5.26, the following results in an error:
4569 // "Ternary operator applied to void, arrays, or structs containing arrays"
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004570 if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
Corentin Wallez0d959252016-07-12 17:26:32 -04004571 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004572 error(loc, "ternary operator is not allowed for void", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004573 return falseExpression;
Corentin Wallez0d959252016-07-12 17:26:32 -04004574 }
4575
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004576 return TIntermediate::AddTernarySelection(cond, trueExpression, falseExpression, loc);
Olli Etuaho52901742015-04-15 13:42:45 +03004577}
Olli Etuaho49300862015-02-20 14:54:49 +02004578
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004579//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004580// Parse an array of strings using yyparse.
4581//
4582// Returns 0 for success.
4583//
Jamie Madillb98c3a82015-07-23 14:26:04 -04004584int PaParseStrings(size_t count,
4585 const char *const string[],
4586 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05304587 TParseContext *context)
4588{
Yunchao He4f285442017-04-21 12:15:49 +08004589 if ((count == 0) || (string == nullptr))
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004590 return 1;
4591
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004592 if (glslang_initialize(context))
4593 return 1;
4594
alokp@chromium.org408c45e2012-04-05 15:54:43 +00004595 int error = glslang_scan(count, string, length, context);
4596 if (!error)
4597 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004598
alokp@chromium.org73bc2982012-06-19 18:48:05 +00004599 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00004600
alokp@chromium.org6b495712012-06-29 00:06:58 +00004601 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004602}
Jamie Madill45bcc782016-11-07 13:58:48 -05004603
4604} // namespace sh