blob: 0b9da36abb2bda917637888a9e1c35ddf62d7fa6 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Jamie Madill6b9cb252013-10-17 10:45:47 -04007#include "compiler/translator/ParseContext.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +00008
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00009#include <stdarg.h>
apatrick@chromium.org8187fa82010-06-15 22:09:28 +000010#include <stdio.h>
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000011
daniel@transgaming.comb401a922012-10-26 18:58:24 +000012#include "compiler/preprocessor/SourceLocation.h"
Dmitry Skiba01971112015-07-10 14:54:00 -040013#include "compiler/translator/Cache.h"
Olli Etuahoac5274d2015-02-20 10:19:08 +020014#include "compiler/translator/glslang.h"
15#include "compiler/translator/ValidateSwitch.h"
Olli Etuahob0c645e2015-05-12 14:25:36 +030016#include "compiler/translator/ValidateGlobalInitializer.h"
Olli Etuaho37ad4742015-04-27 13:18:50 +030017#include "compiler/translator/util.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000018
Jamie Madill45bcc782016-11-07 13:58:48 -050019namespace sh
20{
21
alokp@chromium.org8b851c62012-06-15 16:25:11 +000022///////////////////////////////////////////////////////////////////////
23//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000024// Sub- vector and matrix fields
25//
26////////////////////////////////////////////////////////////////////////
27
Martin Radev2cc85b32016-08-05 16:22:53 +030028namespace
29{
30
31const int kWebGLMaxStructNesting = 4;
32
33bool ContainsSampler(const TType &type)
34{
35 if (IsSampler(type.getBasicType()))
36 return true;
37
38 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock())
39 {
40 const TFieldList &fields = type.getStruct()->fields();
41 for (unsigned int i = 0; i < fields.size(); ++i)
42 {
43 if (ContainsSampler(*fields[i]->type()))
44 return true;
45 }
46 }
47
48 return false;
49}
50
51bool ContainsImage(const TType &type)
52{
53 if (IsImage(type.getBasicType()))
54 return true;
55
56 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock())
57 {
58 const TFieldList &fields = type.getStruct()->fields();
59 for (unsigned int i = 0; i < fields.size(); ++i)
60 {
61 if (ContainsImage(*fields[i]->type()))
62 return true;
63 }
64 }
65
66 return false;
67}
68
69} // 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,
77 TInfoSink &is,
78 const ShBuiltInResources &resources)
79 : intermediate(),
80 symbolTable(symt),
81 mDeferredSingleDeclarationErrorCheck(false),
82 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),
96 mDiagnostics(is),
97 mDirectiveHandler(ext,
98 mDiagnostics,
99 mShaderVersion,
100 mShaderType,
101 resources.WEBGL_debug_shader_precision == 1),
Olli Etuahof1cf5e62016-11-22 17:36:49 +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),
109 mComputeShaderLocalSizeDeclared(false),
110 mDeclaringFunction(false)
111{
112 mComputeShaderLocalSize.fill(-1);
113}
114
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000115//
116// Look at a '.' field selector string and change it into offsets
117// for a vector.
118//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400119bool TParseContext::parseVectorFields(const TString &compString,
120 int vecSize,
121 TVectorFields &fields,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530122 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400124 fields.num = (int)compString.size();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530125 if (fields.num > 4)
126 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000127 error(line, "illegal vector field selection", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000128 return false;
129 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000130
Jamie Madillb98c3a82015-07-23 14:26:04 -0400131 enum
132 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000133 exyzw,
134 ergba,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000135 estpq
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000136 } fieldSet[4];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000137
Arun Patole7e7e68d2015-05-22 12:02:25 +0530138 for (int i = 0; i < fields.num; ++i)
139 {
140 switch (compString[i])
141 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400142 case 'x':
143 fields.offsets[i] = 0;
144 fieldSet[i] = exyzw;
145 break;
146 case 'r':
147 fields.offsets[i] = 0;
148 fieldSet[i] = ergba;
149 break;
150 case 's':
151 fields.offsets[i] = 0;
152 fieldSet[i] = estpq;
153 break;
154 case 'y':
155 fields.offsets[i] = 1;
156 fieldSet[i] = exyzw;
157 break;
158 case 'g':
159 fields.offsets[i] = 1;
160 fieldSet[i] = ergba;
161 break;
162 case 't':
163 fields.offsets[i] = 1;
164 fieldSet[i] = estpq;
165 break;
166 case 'z':
167 fields.offsets[i] = 2;
168 fieldSet[i] = exyzw;
169 break;
170 case 'b':
171 fields.offsets[i] = 2;
172 fieldSet[i] = ergba;
173 break;
174 case 'p':
175 fields.offsets[i] = 2;
176 fieldSet[i] = estpq;
177 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530178
Jamie Madillb98c3a82015-07-23 14:26:04 -0400179 case 'w':
180 fields.offsets[i] = 3;
181 fieldSet[i] = exyzw;
182 break;
183 case 'a':
184 fields.offsets[i] = 3;
185 fieldSet[i] = ergba;
186 break;
187 case 'q':
188 fields.offsets[i] = 3;
189 fieldSet[i] = estpq;
190 break;
191 default:
192 error(line, "illegal vector field selection", compString.c_str());
193 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000194 }
195 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000196
Arun Patole7e7e68d2015-05-22 12:02:25 +0530197 for (int i = 0; i < fields.num; ++i)
198 {
199 if (fields.offsets[i] >= vecSize)
200 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400201 error(line, "vector field selection out of range", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000202 return false;
203 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204
Arun Patole7e7e68d2015-05-22 12:02:25 +0530205 if (i > 0)
206 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400207 if (fieldSet[i] != fieldSet[i - 1])
Arun Patole7e7e68d2015-05-22 12:02:25 +0530208 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400209 error(line, "illegal - vector component fields not from the same set",
210 compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000211 return false;
212 }
213 }
214 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000215
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000216 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000217}
218
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219///////////////////////////////////////////////////////////////////////
220//
221// Errors
222//
223////////////////////////////////////////////////////////////////////////
224
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225//
226// Used by flex/bison to output all syntax and parsing errors.
227//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530228void TParseContext::error(const TSourceLoc &loc,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400229 const char *reason,
230 const char *token,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530231 const char *extraInfo)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000232{
Olli Etuaho1cc598f2016-08-18 13:50:30 +0300233 mDiagnostics.error(loc, reason, token, extraInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000234}
235
Arun Patole7e7e68d2015-05-22 12:02:25 +0530236void TParseContext::warning(const TSourceLoc &loc,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400237 const char *reason,
238 const char *token,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530239 const char *extraInfo)
240{
Olli Etuaho1cc598f2016-08-18 13:50:30 +0300241 mDiagnostics.warning(loc, reason, token, extraInfo);
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,
247 const char *token,
248 const char *extraInfo)
249{
250 if (isError)
251 {
252 error(loc, reason, token, extraInfo);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200253 }
254 else
255 {
256 warning(loc, reason, token, extraInfo);
257 }
258}
259
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260//
261// Same error message for all places assignments don't work.
262//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530263void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000264{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000265 std::stringstream extraInfoStream;
266 extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
267 std::string extraInfo = extraInfoStream.str();
268 error(line, "", op, extraInfo.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269}
270
271//
272// Same error message for all places unary operations don't work.
273//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530274void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000275{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000276 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400277 extraInfoStream << "no operation '" << op << "' exists that takes an operand of type "
278 << operand << " (or there is no acceptable conversion)";
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000279 std::string extraInfo = extraInfoStream.str();
280 error(line, " wrong operand type", op, extraInfo.c_str());
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{
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000291 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400292 extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '"
293 << left << "' and a right operand of type '" << right
294 << "' (or there is no acceptable conversion)";
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000295 std::string extraInfo = extraInfoStream.str();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530296 error(line, " wrong operand types ", op, extraInfo.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000297}
298
Olli Etuaho856c4972016-08-08 11:38:39 +0300299void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
300 TPrecision precision,
301 TBasicType type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530302{
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400303 if (!mChecksPrecisionErrors)
Olli Etuaho383b7912016-08-05 11:22:59 +0300304 return;
Martin Radev70866b82016-07-22 15:27:42 +0300305
306 if (precision != EbpUndefined && !SupportsPrecision(type))
307 {
308 error(line, "illegal type for precision qualifier", getBasicString(type));
309 }
310
Olli Etuaho183d7e22015-11-20 15:59:09 +0200311 if (precision == EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530312 {
Olli Etuaho183d7e22015-11-20 15:59:09 +0200313 switch (type)
314 {
315 case EbtFloat:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400316 error(line, "No precision specified for (float)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300317 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200318 case EbtInt:
319 case EbtUInt:
320 UNREACHABLE(); // there's always a predeclared qualifier
Jamie Madillb98c3a82015-07-23 14:26:04 -0400321 error(line, "No precision specified (int)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300322 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200323 default:
324 if (IsSampler(type))
325 {
326 error(line, "No precision specified (sampler)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300327 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200328 }
Martin Radev2cc85b32016-08-05 16:22:53 +0300329 if (IsImage(type))
330 {
331 error(line, "No precision specified (image)", "");
332 return;
333 }
Olli Etuaho183d7e22015-11-20 15:59:09 +0200334 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000335 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000336}
337
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000338// Both test and if necessary, spit out an error, to see if the node is really
339// an l-value that can be operated on this way.
Olli Etuaho856c4972016-08-08 11:38:39 +0300340bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500342 TIntermSymbol *symNode = node->getAsSymbolNode();
343 TIntermBinary *binaryNode = node->getAsBinaryNode();
Olli Etuahob6fa0432016-09-28 16:28:05 +0100344 TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
345
346 if (swizzleNode)
347 {
348 bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
349 if (ok && swizzleNode->hasDuplicateOffsets())
350 {
351 error(line, " l-value of swizzle cannot have duplicate components", op);
352 return false;
353 }
354 return ok;
355 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000356
Arun Patole7e7e68d2015-05-22 12:02:25 +0530357 if (binaryNode)
358 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400359 switch (binaryNode->getOp())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530360 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400361 case EOpIndexDirect:
362 case EOpIndexIndirect:
363 case EOpIndexDirectStruct:
364 case EOpIndexDirectInterfaceBlock:
Olli Etuaho856c4972016-08-08 11:38:39 +0300365 return checkCanBeLValue(line, op, binaryNode->getLeft());
Jamie Madillb98c3a82015-07-23 14:26:04 -0400366 default:
367 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000368 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000369 error(line, " l-value required", op);
Olli Etuaho8a176262016-08-16 14:23:01 +0300370 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000371 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000372
Arun Patole7e7e68d2015-05-22 12:02:25 +0530373 const char *symbol = 0;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000374 if (symNode != 0)
375 symbol = symNode->getSymbol().c_str();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000376
Arun Patole7e7e68d2015-05-22 12:02:25 +0530377 const char *message = 0;
378 switch (node->getQualifier())
379 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400380 case EvqConst:
381 message = "can't modify a const";
382 break;
383 case EvqConstReadOnly:
384 message = "can't modify a const";
385 break;
386 case EvqAttribute:
387 message = "can't modify an attribute";
388 break;
389 case EvqFragmentIn:
390 message = "can't modify an input";
391 break;
392 case EvqVertexIn:
393 message = "can't modify an input";
394 break;
395 case EvqUniform:
396 message = "can't modify a uniform";
397 break;
398 case EvqVaryingIn:
399 message = "can't modify a varying";
400 break;
401 case EvqFragCoord:
402 message = "can't modify gl_FragCoord";
403 break;
404 case EvqFrontFacing:
405 message = "can't modify gl_FrontFacing";
406 break;
407 case EvqPointCoord:
408 message = "can't modify gl_PointCoord";
409 break;
Martin Radevb0883602016-08-04 17:48:58 +0300410 case EvqNumWorkGroups:
411 message = "can't modify gl_NumWorkGroups";
412 break;
413 case EvqWorkGroupSize:
414 message = "can't modify gl_WorkGroupSize";
415 break;
416 case EvqWorkGroupID:
417 message = "can't modify gl_WorkGroupID";
418 break;
419 case EvqLocalInvocationID:
420 message = "can't modify gl_LocalInvocationID";
421 break;
422 case EvqGlobalInvocationID:
423 message = "can't modify gl_GlobalInvocationID";
424 break;
425 case EvqLocalInvocationIndex:
426 message = "can't modify gl_LocalInvocationIndex";
427 break;
Martin Radev802abe02016-08-04 17:48:32 +0300428 case EvqComputeIn:
429 message = "can't modify work group size variable";
430 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400431 default:
432 //
433 // Type that can't be written to?
434 //
435 if (node->getBasicType() == EbtVoid)
436 {
437 message = "can't modify void";
438 }
439 if (IsSampler(node->getBasicType()))
440 {
441 message = "can't modify a sampler";
442 }
Martin Radev2cc85b32016-08-05 16:22:53 +0300443 if (IsImage(node->getBasicType()))
444 {
445 message = "can't modify an image";
446 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000447 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000448
Arun Patole7e7e68d2015-05-22 12:02:25 +0530449 if (message == 0 && binaryNode == 0 && symNode == 0)
450 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000451 error(line, " l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000452
Olli Etuaho8a176262016-08-16 14:23:01 +0300453 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000454 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000455
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000456 //
457 // Everything else is okay, no error.
458 //
459 if (message == 0)
Olli Etuaho8a176262016-08-16 14:23:01 +0300460 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000461
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000462 //
463 // If we get here, we have an error and a message.
464 //
Arun Patole7e7e68d2015-05-22 12:02:25 +0530465 if (symNode)
466 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000467 std::stringstream extraInfoStream;
468 extraInfoStream << "\"" << symbol << "\" (" << message << ")";
469 std::string extraInfo = extraInfoStream.str();
470 error(line, " l-value required", op, extraInfo.c_str());
471 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530472 else
473 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000474 std::stringstream extraInfoStream;
475 extraInfoStream << "(" << message << ")";
476 std::string extraInfo = extraInfoStream.str();
477 error(line, " l-value required", op, extraInfo.c_str());
478 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000479
Olli Etuaho8a176262016-08-16 14:23:01 +0300480 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000481}
482
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000483// Both test, and if necessary spit out an error, to see if the node is really
484// a constant.
Olli Etuaho856c4972016-08-08 11:38:39 +0300485void TParseContext::checkIsConst(TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000486{
Olli Etuaho383b7912016-08-05 11:22:59 +0300487 if (node->getQualifier() != EvqConst)
488 {
489 error(node->getLine(), "constant expression required", "");
490 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000491}
492
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000493// Both test, and if necessary spit out an error, to see if the node is really
494// an integer.
Olli Etuaho856c4972016-08-08 11:38:39 +0300495void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000496{
Olli Etuaho383b7912016-08-05 11:22:59 +0300497 if (!node->isScalarInt())
498 {
499 error(node->getLine(), "integer expression required", token);
500 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000501}
502
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000503// Both test, and if necessary spit out an error, to see if we are currently
504// globally scoped.
Qiankun Miaof69682b2016-08-16 14:50:42 +0800505bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000506{
Olli Etuaho856c4972016-08-08 11:38:39 +0300507 if (!symbolTable.atGlobalLevel())
Olli Etuaho383b7912016-08-05 11:22:59 +0300508 {
509 error(line, "only allowed at global scope", token);
Qiankun Miaof69682b2016-08-16 14:50:42 +0800510 return false;
Olli Etuaho383b7912016-08-05 11:22:59 +0300511 }
Qiankun Miaof69682b2016-08-16 14:50:42 +0800512 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000513}
514
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000515// For now, keep it simple: if it starts "gl_", it's reserved, independent
516// of scope. Except, if the symbol table is at the built-in push-level,
517// which is when we are parsing built-ins.
alokp@chromium.org613ef312010-07-21 18:54:22 +0000518// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
519// webgl shader.
Olli Etuaho856c4972016-08-08 11:38:39 +0300520bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000521{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530522 static const char *reservedErrMsg = "reserved built-in name";
523 if (!symbolTable.atBuiltInLevel())
524 {
525 if (identifier.compare(0, 3, "gl_") == 0)
526 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000527 error(line, reservedErrMsg, "gl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300528 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000529 }
Jamie Madillacb4b812016-11-07 13:50:29 -0500530 if (sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530531 {
532 if (identifier.compare(0, 6, "webgl_") == 0)
533 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000534 error(line, reservedErrMsg, "webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300535 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000536 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530537 if (identifier.compare(0, 7, "_webgl_") == 0)
538 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000539 error(line, reservedErrMsg, "_webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300540 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000541 }
542 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530543 if (identifier.find("__") != TString::npos)
544 {
545 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400546 "identifiers containing two consecutive underscores (__) are reserved as "
547 "possible future keywords",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530548 identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300549 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000550 }
551 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000552
Olli Etuaho8a176262016-08-16 14:23:01 +0300553 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000554}
555
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000556// Make sure there is enough data provided to the constructor to build
557// something of the type of the constructor. Also returns the type of
558// the constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +0300559bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
560 TIntermNode *argumentsNode,
561 const TFunction &function,
562 TOperator op,
563 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000564{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000565 bool constructingMatrix = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400566 switch (op)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530567 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400568 case EOpConstructMat2:
569 case EOpConstructMat2x3:
570 case EOpConstructMat2x4:
571 case EOpConstructMat3x2:
572 case EOpConstructMat3:
573 case EOpConstructMat3x4:
574 case EOpConstructMat4x2:
575 case EOpConstructMat4x3:
576 case EOpConstructMat4:
577 constructingMatrix = true;
578 break;
579 default:
580 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000581 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000582
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000583 //
584 // Note: It's okay to have too many components available, but not okay to have unused
585 // arguments. 'full' will go to true when enough args have been seen. If we loop
586 // again, there is an extra argument, so 'overfull' will become true.
587 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000588
Jamie Madillb98c3a82015-07-23 14:26:04 -0400589 size_t size = 0;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400590 bool full = false;
591 bool overFull = false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000592 bool matrixInMatrix = false;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500593 bool arrayArg = false;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530594 for (size_t i = 0; i < function.getParamCount(); ++i)
595 {
Dmitry Skibaefa3d8e2015-06-22 14:52:10 -0700596 const TConstParameter &param = function.getParam(i);
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000597 size += param.type->getObjectSize();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530598
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000599 if (constructingMatrix && param.type->isMatrix())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000600 matrixInMatrix = true;
601 if (full)
602 overFull = true;
Olli Etuaho856c4972016-08-08 11:38:39 +0300603 if (op != EOpConstructStruct && !type.isArray() && size >= type.getObjectSize())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000604 full = true;
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000605 if (param.type->isArray())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000606 arrayArg = true;
607 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530608
Olli Etuaho856c4972016-08-08 11:38:39 +0300609 if (type.isArray())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300610 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300611 // The size of an unsized constructor should already have been determined.
612 ASSERT(!type.isUnsizedArray());
613 if (static_cast<size_t>(type.getArraySize()) != function.getParamCount())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300614 {
615 error(line, "array constructor needs one argument per array element", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300616 return false;
Olli Etuaho376f1b52015-04-13 13:23:41 +0300617 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000618 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000619
Arun Patole7e7e68d2015-05-22 12:02:25 +0530620 if (arrayArg && op != EOpConstructStruct)
621 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000622 error(line, "constructing from a non-dereferenced array", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300623 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000624 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000625
Olli Etuaho856c4972016-08-08 11:38:39 +0300626 if (matrixInMatrix && !type.isArray())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530627 {
628 if (function.getParamCount() != 1)
629 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400630 error(line, "constructing matrix from matrix can only take one argument",
631 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300632 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000633 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000634 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000635
Arun Patole7e7e68d2015-05-22 12:02:25 +0530636 if (overFull)
637 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000638 error(line, "too many arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300639 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000640 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530641
Olli Etuaho856c4972016-08-08 11:38:39 +0300642 if (op == EOpConstructStruct && !type.isArray() &&
643 type.getStruct()->fields().size() != function.getParamCount())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530644 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400645 error(line,
646 "Number of constructor parameters does not match the number of structure fields",
647 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300648 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000649 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000650
Olli Etuaho856c4972016-08-08 11:38:39 +0300651 if (!type.isMatrix() || !matrixInMatrix)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530652 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300653 if ((op != EOpConstructStruct && size != 1 && size < type.getObjectSize()) ||
654 (op == EOpConstructStruct && size < type.getObjectSize()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530655 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000656 error(line, "not enough data provided for construction", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300657 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000658 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000659 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000660
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200661 if (argumentsNode == nullptr)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530662 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200663 error(line, "constructor does not have any arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300664 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000665 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200666
667 TIntermAggregate *argumentsAgg = argumentsNode->getAsAggregate();
668 for (TIntermNode *&argNode : *argumentsAgg->getSequence())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530669 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200670 TIntermTyped *argTyped = argNode->getAsTyped();
671 ASSERT(argTyped != nullptr);
672 if (op != EOpConstructStruct && IsSampler(argTyped->getBasicType()))
673 {
674 error(line, "cannot convert a sampler", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300675 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200676 }
Martin Radev2cc85b32016-08-05 16:22:53 +0300677 if (op != EOpConstructStruct && IsImage(argTyped->getBasicType()))
678 {
679 error(line, "cannot convert an image", "constructor");
680 return false;
681 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200682 if (argTyped->getBasicType() == EbtVoid)
683 {
684 error(line, "cannot convert a void", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300685 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200686 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000687 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000688
Olli Etuaho856c4972016-08-08 11:38:39 +0300689 if (type.isArray())
690 {
691 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
692 // the array.
693 for (TIntermNode *&argNode : *argumentsAgg->getSequence())
694 {
695 const TType &argType = argNode->getAsTyped()->getType();
696 // It has already been checked that the argument is not an array.
697 ASSERT(!argType.isArray());
698 if (!argType.sameElementType(type))
699 {
700 error(line, "Array constructor argument has an incorrect type", "Error");
Olli Etuaho8a176262016-08-16 14:23:01 +0300701 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300702 }
703 }
704 }
705 else if (op == EOpConstructStruct)
706 {
707 const TFieldList &fields = type.getStruct()->fields();
708 TIntermSequence *args = argumentsAgg->getSequence();
709
710 for (size_t i = 0; i < fields.size(); i++)
711 {
712 if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type())
713 {
714 error(line, "Structure constructor arguments do not match structure fields",
715 "Error");
Olli Etuaho8a176262016-08-16 14:23:01 +0300716 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300717 }
718 }
719 }
720
Olli Etuaho8a176262016-08-16 14:23:01 +0300721 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000722}
723
Jamie Madillb98c3a82015-07-23 14:26:04 -0400724// This function checks to see if a void variable has been declared and raise an error message for
725// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000726//
727// returns true in case of an error
728//
Olli Etuaho856c4972016-08-08 11:38:39 +0300729bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400730 const TString &identifier,
731 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000732{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300733 if (type == EbtVoid)
734 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000735 error(line, "illegal use of type 'void'", identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300736 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300737 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000738
Olli Etuaho8a176262016-08-16 14:23:01 +0300739 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000740}
741
Jamie Madillb98c3a82015-07-23 14:26:04 -0400742// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300743// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300744void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000745{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530746 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
747 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000748 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530749 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000750}
751
Jamie Madillb98c3a82015-07-23 14:26:04 -0400752// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300753// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300754void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000755{
Martin Radev4a9cd802016-09-01 16:51:51 +0300756 if (pType.getBasicType() != EbtBool || pType.isAggregate())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530757 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000758 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530759 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000760}
761
Olli Etuaho856c4972016-08-08 11:38:39 +0300762bool TParseContext::checkIsNotSampler(const TSourceLoc &line,
Martin Radev4a9cd802016-09-01 16:51:51 +0300763 const TTypeSpecifierNonArray &pType,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400764 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000765{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530766 if (pType.type == EbtStruct)
767 {
Martin Radev2cc85b32016-08-05 16:22:53 +0300768 if (ContainsSampler(*pType.userDef))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530769 {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000770 error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
Olli Etuaho8a176262016-08-16 14:23:01 +0300771 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000772 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530773
Olli Etuaho8a176262016-08-16 14:23:01 +0300774 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530775 }
776 else if (IsSampler(pType.type))
777 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000778 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300779 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000780 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000781
Olli Etuaho8a176262016-08-16 14:23:01 +0300782 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000783}
784
Martin Radev2cc85b32016-08-05 16:22:53 +0300785bool TParseContext::checkIsNotImage(const TSourceLoc &line,
786 const TTypeSpecifierNonArray &pType,
787 const char *reason)
788{
789 if (pType.type == EbtStruct)
790 {
791 if (ContainsImage(*pType.userDef))
792 {
793 error(line, reason, getBasicString(pType.type), "(structure contains an image)");
794
795 return false;
796 }
797
798 return true;
799 }
800 else if (IsImage(pType.type))
801 {
802 error(line, reason, getBasicString(pType.type));
803
804 return false;
805 }
806
807 return true;
808}
809
Olli Etuaho856c4972016-08-08 11:38:39 +0300810void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
811 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400812{
813 if (pType.layoutQualifier.location != -1)
814 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400815 error(line, "location must only be specified for a single input or output variable",
816 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400817 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400818}
819
Olli Etuaho856c4972016-08-08 11:38:39 +0300820void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
821 const TLayoutQualifier &layoutQualifier)
822{
823 if (layoutQualifier.location != -1)
824 {
825 error(location, "invalid layout qualifier:", "location",
826 "only valid on program inputs and outputs");
827 }
828}
829
Martin Radev2cc85b32016-08-05 16:22:53 +0300830void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
831 TQualifier qualifier,
832 const TType &type)
833{
834 checkOutParameterIsNotSampler(line, qualifier, type);
835 checkOutParameterIsNotImage(line, qualifier, type);
836}
837
Olli Etuaho856c4972016-08-08 11:38:39 +0300838void TParseContext::checkOutParameterIsNotSampler(const TSourceLoc &line,
839 TQualifier qualifier,
840 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000841{
Martin Radev2cc85b32016-08-05 16:22:53 +0300842 ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
843 if (IsSampler(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530844 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000845 error(line, "samplers cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000846 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000847}
848
Martin Radev2cc85b32016-08-05 16:22:53 +0300849void TParseContext::checkOutParameterIsNotImage(const TSourceLoc &line,
850 TQualifier qualifier,
851 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000852{
Martin Radev2cc85b32016-08-05 16:22:53 +0300853 ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
854 if (IsImage(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530855 {
Martin Radev2cc85b32016-08-05 16:22:53 +0300856 error(line, "images cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000857 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000858}
859
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000860// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300861unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000862{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530863 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000864
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200865 // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
866 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
867 // fold as array size.
868 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000869 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000870 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300871 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000872 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000873
Olli Etuaho856c4972016-08-08 11:38:39 +0300874 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400875
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000876 if (constant->getBasicType() == EbtUInt)
877 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300878 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000879 }
880 else
881 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300882 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000883
Olli Etuaho856c4972016-08-08 11:38:39 +0300884 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000885 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400886 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300887 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000888 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400889
Olli Etuaho856c4972016-08-08 11:38:39 +0300890 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -0400891 }
892
Olli Etuaho856c4972016-08-08 11:38:39 +0300893 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -0400894 {
895 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300896 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400897 }
898
899 // The size of arrays is restricted here to prevent issues further down the
900 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
901 // 4096 registers so this should be reasonable even for aggressively optimizable code.
902 const unsigned int sizeLimit = 65536;
903
Olli Etuaho856c4972016-08-08 11:38:39 +0300904 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -0400905 {
906 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300907 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000908 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300909
910 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000911}
912
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000913// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +0300914bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
915 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000916{
Olli Etuaho8a176262016-08-16 14:23:01 +0300917 if ((elementQualifier.qualifier == EvqAttribute) ||
918 (elementQualifier.qualifier == EvqVertexIn) ||
919 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +0300920 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400921 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300922 TType(elementQualifier).getQualifierString());
923 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000924 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000925
Olli Etuaho8a176262016-08-16 14:23:01 +0300926 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000927}
928
Olli Etuaho8a176262016-08-16 14:23:01 +0300929// See if this element type can be formed into an array.
930bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000931{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000932 //
933 // Can the type be an array?
934 //
Olli Etuaho8a176262016-08-16 14:23:01 +0300935 if (elementType.array)
Jamie Madill06145232015-05-13 13:10:01 -0400936 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300937 error(line, "cannot declare arrays of arrays",
938 TType(elementType).getCompleteString().c_str());
939 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000940 }
Olli Etuahocc36b982015-07-10 14:14:18 +0300941 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
942 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
943 // 4.3.4).
Martin Radev4a9cd802016-09-01 16:51:51 +0300944 if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
Olli Etuaho8a176262016-08-16 14:23:01 +0300945 sh::IsVarying(elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +0300946 {
947 error(line, "cannot declare arrays of structs of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300948 TType(elementType).getCompleteString().c_str());
949 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +0300950 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000951
Olli Etuaho8a176262016-08-16 14:23:01 +0300952 return true;
953}
954
955// Check if this qualified element type can be formed into an array.
956bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
957 const TPublicType &elementType)
958{
959 if (checkIsValidTypeForArray(indexLocation, elementType))
960 {
961 return checkIsValidQualifierForArray(indexLocation, elementType);
962 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000963 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000964}
965
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000966// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +0300967void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
968 const TString &identifier,
969 TPublicType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000970{
Olli Etuaho3739d232015-04-08 12:23:44 +0300971 ASSERT(type != nullptr);
972 if (type->qualifier == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000973 {
974 // Make the qualifier make sense.
Olli Etuaho3739d232015-04-08 12:23:44 +0300975 type->qualifier = EvqTemporary;
976
977 // Generate informative error messages for ESSL1.
978 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400979 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000980 {
Arun Patole7e7e68d2015-05-22 12:02:25 +0530981 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400982 "structures containing arrays may not be declared constant since they cannot be "
983 "initialized",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530984 identifier.c_str());
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000985 }
986 else
987 {
988 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
989 }
Olli Etuaho383b7912016-08-05 11:22:59 +0300990 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000991 }
Olli Etuaho376f1b52015-04-13 13:23:41 +0300992 if (type->isUnsizedArray())
993 {
994 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
Olli Etuaho376f1b52015-04-13 13:23:41 +0300995 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000996}
997
Olli Etuaho2935c582015-04-08 14:32:06 +0300998// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000999// and update the symbol table.
1000//
Olli Etuaho2935c582015-04-08 14:32:06 +03001001// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001002//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001003bool TParseContext::declareVariable(const TSourceLoc &line,
1004 const TString &identifier,
1005 const TType &type,
Olli Etuaho2935c582015-04-08 14:32:06 +03001006 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001007{
Olli Etuaho2935c582015-04-08 14:32:06 +03001008 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001009
Olli Etuaho856c4972016-08-08 11:38:39 +03001010 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001011
Olli Etuaho2935c582015-04-08 14:32:06 +03001012 // gl_LastFragData may be redeclared with a new precision qualifier
1013 if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
1014 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001015 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
1016 symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Olli Etuaho856c4972016-08-08 11:38:39 +03001017 if (static_cast<int>(type.getArraySize()) == maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +03001018 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001019 if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +03001020 {
Olli Etuaho8a176262016-08-16 14:23:01 +03001021 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
Olli Etuaho2935c582015-04-08 14:32:06 +03001022 }
1023 }
1024 else
1025 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001026 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
1027 identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +03001028 return false;
1029 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001030 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001031
Olli Etuaho8a176262016-08-16 14:23:01 +03001032 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +03001033 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001034
Olli Etuaho2935c582015-04-08 14:32:06 +03001035 (*variable) = new TVariable(&identifier, type);
1036 if (!symbolTable.declare(*variable))
1037 {
1038 error(line, "redefinition", identifier.c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -04001039 *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +03001040 return false;
1041 }
1042
Olli Etuaho8a176262016-08-16 14:23:01 +03001043 if (!checkIsNonVoid(line, identifier, type.getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +03001044 return false;
1045
1046 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001047}
1048
Martin Radev70866b82016-07-22 15:27:42 +03001049void TParseContext::checkIsParameterQualifierValid(
1050 const TSourceLoc &line,
1051 const TTypeQualifierBuilder &typeQualifierBuilder,
1052 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301053{
Olli Etuaho613b9592016-09-05 12:05:53 +03001054 TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(&mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03001055
1056 if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301057 {
Martin Radev2cc85b32016-08-05 16:22:53 +03001058 checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type);
1059 }
1060
1061 if (!IsImage(type->getBasicType()))
1062 {
1063 checkIsMemoryQualifierNotSpecified(typeQualifier.memoryQualifier, line);
1064 }
1065 else
1066 {
1067 type->setMemoryQualifier(typeQualifier.memoryQualifier);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001068 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001069
Martin Radev70866b82016-07-22 15:27:42 +03001070 type->setQualifier(typeQualifier.qualifier);
1071
1072 if (typeQualifier.precision != EbpUndefined)
1073 {
1074 type->setPrecision(typeQualifier.precision);
1075 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001076}
1077
Olli Etuaho856c4972016-08-08 11:38:39 +03001078bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001079{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001080 const TExtensionBehavior &extBehavior = extensionBehavior();
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001081 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
Arun Patole7e7e68d2015-05-22 12:02:25 +05301082 if (iter == extBehavior.end())
1083 {
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001084 error(line, "extension", extension.c_str(), "is not supported");
Olli Etuaho8a176262016-08-16 14:23:01 +03001085 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001086 }
zmo@google.comf5450912011-09-09 01:37:19 +00001087 // In GLSL ES, an extension's default behavior is "disable".
Arun Patole7e7e68d2015-05-22 12:02:25 +05301088 if (iter->second == EBhDisable || iter->second == EBhUndefined)
1089 {
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001090 error(line, "extension", extension.c_str(), "is disabled");
Olli Etuaho8a176262016-08-16 14:23:01 +03001091 return false;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001092 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301093 if (iter->second == EBhWarn)
1094 {
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001095 warning(line, "extension", extension.c_str(), "is being used");
Olli Etuaho8a176262016-08-16 14:23:01 +03001096 return true;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001097 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001098
Olli Etuaho8a176262016-08-16 14:23:01 +03001099 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001100}
1101
Jamie Madillb98c3a82015-07-23 14:26:04 -04001102// These checks are common for all declarations starting a declarator list, and declarators that
1103// follow an empty declaration.
Olli Etuaho383b7912016-08-05 11:22:59 +03001104void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001105 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -04001106{
Olli Etuahofa33d582015-04-09 14:33:12 +03001107 switch (publicType.qualifier)
1108 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001109 case EvqVaryingIn:
1110 case EvqVaryingOut:
1111 case EvqAttribute:
1112 case EvqVertexIn:
1113 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +03001114 case EvqComputeIn:
Martin Radev4a9cd802016-09-01 16:51:51 +03001115 if (publicType.getBasicType() == EbtStruct)
Jamie Madillb98c3a82015-07-23 14:26:04 -04001116 {
1117 error(identifierLocation, "cannot be used with a structure",
1118 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +03001119 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001120 }
Olli Etuahofa33d582015-04-09 14:33:12 +03001121
Jamie Madillb98c3a82015-07-23 14:26:04 -04001122 default:
1123 break;
Olli Etuahofa33d582015-04-09 14:33:12 +03001124 }
1125
Jamie Madillb98c3a82015-07-23 14:26:04 -04001126 if (publicType.qualifier != EvqUniform &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001127 !checkIsNotSampler(identifierLocation, publicType.typeSpecifierNonArray,
1128 "samplers must be uniform"))
Olli Etuahofa33d582015-04-09 14:33:12 +03001129 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001130 return;
Olli Etuahofa33d582015-04-09 14:33:12 +03001131 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001132 if (publicType.qualifier != EvqUniform &&
1133 !checkIsNotImage(identifierLocation, publicType.typeSpecifierNonArray,
1134 "images must be uniform"))
1135 {
1136 return;
1137 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001138
1139 // check for layout qualifier issues
1140 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
1141
1142 if (layoutQualifier.matrixPacking != EmpUnspecified)
1143 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001144 error(identifierLocation, "layout qualifier",
1145 getMatrixPackingString(layoutQualifier.matrixPacking),
Olli Etuahofa33d582015-04-09 14:33:12 +03001146 "only valid for interface blocks");
Olli Etuaho383b7912016-08-05 11:22:59 +03001147 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001148 }
1149
1150 if (layoutQualifier.blockStorage != EbsUnspecified)
1151 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001152 error(identifierLocation, "layout qualifier",
1153 getBlockStorageString(layoutQualifier.blockStorage),
Olli Etuahofa33d582015-04-09 14:33:12 +03001154 "only valid for interface blocks");
Olli Etuaho383b7912016-08-05 11:22:59 +03001155 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001156 }
1157
Olli Etuaho383b7912016-08-05 11:22:59 +03001158 if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut)
Jamie Madilla5efff92013-06-06 11:56:47 -04001159 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001160 checkLocationIsNotSpecified(identifierLocation, publicType.layoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04001161 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001162
1163 if (IsImage(publicType.getBasicType()))
1164 {
1165
1166 switch (layoutQualifier.imageInternalFormat)
1167 {
1168 case EiifRGBA32F:
1169 case EiifRGBA16F:
1170 case EiifR32F:
1171 case EiifRGBA8:
1172 case EiifRGBA8_SNORM:
1173 if (!IsFloatImage(publicType.getBasicType()))
1174 {
1175 error(identifierLocation,
1176 "internal image format requires a floating image type",
1177 getBasicString(publicType.getBasicType()));
1178 return;
1179 }
1180 break;
1181 case EiifRGBA32I:
1182 case EiifRGBA16I:
1183 case EiifRGBA8I:
1184 case EiifR32I:
1185 if (!IsIntegerImage(publicType.getBasicType()))
1186 {
1187 error(identifierLocation,
1188 "internal image format requires an integer image type",
1189 getBasicString(publicType.getBasicType()));
1190 return;
1191 }
1192 break;
1193 case EiifRGBA32UI:
1194 case EiifRGBA16UI:
1195 case EiifRGBA8UI:
1196 case EiifR32UI:
1197 if (!IsUnsignedImage(publicType.getBasicType()))
1198 {
1199 error(identifierLocation,
1200 "internal image format requires an unsigned image type",
1201 getBasicString(publicType.getBasicType()));
1202 return;
1203 }
1204 break;
1205 case EiifUnspecified:
1206 error(identifierLocation, "layout qualifier", "No image internal format specified");
1207 return;
1208 default:
1209 error(identifierLocation, "layout qualifier", "unrecognized token");
1210 return;
1211 }
1212
1213 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
1214 switch (layoutQualifier.imageInternalFormat)
1215 {
1216 case EiifR32F:
1217 case EiifR32I:
1218 case EiifR32UI:
1219 break;
1220 default:
1221 if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
1222 {
1223 error(identifierLocation, "layout qualifier",
1224 "Except for images with the r32f, r32i and r32ui format qualifiers, "
1225 "image variables must be qualified readonly and/or writeonly");
1226 return;
1227 }
1228 break;
1229 }
1230 }
1231 else
1232 {
1233
1234 if (!checkInternalFormatIsNotSpecified(identifierLocation,
1235 layoutQualifier.imageInternalFormat))
1236 {
1237 return;
1238 }
1239
1240 if (!checkIsMemoryQualifierNotSpecified(publicType.memoryQualifier, identifierLocation))
1241 {
1242 return;
1243 }
1244 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001245}
1246
Olli Etuaho856c4972016-08-08 11:38:39 +03001247void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1248 const TString &layoutQualifierName,
1249 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001250{
1251
1252 if (mShaderVersion < versionRequired)
1253 {
1254 error(location, "invalid layout qualifier:", layoutQualifierName.c_str(), "not supported");
Martin Radev802abe02016-08-04 17:48:32 +03001255 }
1256}
1257
Olli Etuaho856c4972016-08-08 11:38:39 +03001258bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1259 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001260{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001261 const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
Martin Radev802abe02016-08-04 17:48:32 +03001262 for (size_t i = 0u; i < localSize.size(); ++i)
1263 {
1264 if (localSize[i] != -1)
1265 {
Martin Radev4c4c8e72016-08-04 12:25:34 +03001266 error(location, "invalid layout qualifier:", getWorkGroupSizeString(i),
Martin Radev802abe02016-08-04 17:48:32 +03001267 "only valid when used with 'in' in a compute shader global layout declaration");
Olli Etuaho8a176262016-08-16 14:23:01 +03001268 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001269 }
1270 }
1271
Olli Etuaho8a176262016-08-16 14:23:01 +03001272 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001273}
1274
Martin Radev2cc85b32016-08-05 16:22:53 +03001275bool TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
1276 TLayoutImageInternalFormat internalFormat)
1277{
1278 if (internalFormat != EiifUnspecified)
1279 {
1280 error(location, "invalid layout qualifier:", getImageInternalFormatString(internalFormat),
1281 "only valid when used with images");
1282 return false;
1283 }
1284 return true;
1285}
1286
Olli Etuaho383b7912016-08-05 11:22:59 +03001287void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
Olli Etuaho856c4972016-08-08 11:38:39 +03001288 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001289{
1290 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1291 {
1292 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1293 if (qual == EvqOut || qual == EvqInOut)
1294 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001295 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho8a176262016-08-16 14:23:01 +03001296 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001297 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001298 error(argument->getLine(),
Jamie Madillb98c3a82015-07-23 14:26:04 -04001299 "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
Olli Etuaho383b7912016-08-05 11:22:59 +03001300 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001301 }
1302 }
1303 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001304}
1305
Martin Radev70866b82016-07-22 15:27:42 +03001306void TParseContext::checkInvariantVariableQualifier(bool invariant,
1307 const TQualifier qualifier,
1308 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001309{
Martin Radev70866b82016-07-22 15:27:42 +03001310 if (!invariant)
1311 return;
1312
1313 if (mShaderVersion < 300)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001314 {
Martin Radev70866b82016-07-22 15:27:42 +03001315 // input variables in the fragment shader can be also qualified as invariant
1316 if (!sh::CanBeInvariantESSL1(qualifier))
1317 {
1318 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1319 }
1320 }
1321 else
1322 {
1323 if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
1324 {
1325 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1326 }
Olli Etuaho37ad4742015-04-27 13:18:50 +03001327 }
1328}
1329
Arun Patole7e7e68d2015-05-22 12:02:25 +05301330bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001331{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001332 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001333 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1334 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001335}
1336
Arun Patole7e7e68d2015-05-22 12:02:25 +05301337bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001338{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001339 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001340}
1341
Jamie Madillb98c3a82015-07-23 14:26:04 -04001342void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1343 const char *extName,
1344 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001345{
1346 pp::SourceLocation srcLoc;
1347 srcLoc.file = loc.first_file;
1348 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001349 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001350}
1351
Jamie Madillb98c3a82015-07-23 14:26:04 -04001352void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1353 const char *name,
1354 const char *value,
1355 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001356{
1357 pp::SourceLocation srcLoc;
1358 srcLoc.file = loc.first_file;
1359 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001360 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001361}
1362
Martin Radev4c4c8e72016-08-04 12:25:34 +03001363sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
Martin Radev802abe02016-08-04 17:48:32 +03001364{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001365 sh::WorkGroupSize result;
Martin Radev802abe02016-08-04 17:48:32 +03001366 for (size_t i = 0u; i < result.size(); ++i)
1367 {
1368 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1369 {
1370 result[i] = 1;
1371 }
1372 else
1373 {
1374 result[i] = mComputeShaderLocalSize[i];
1375 }
1376 }
1377 return result;
1378}
1379
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001380/////////////////////////////////////////////////////////////////////////////////
1381//
1382// Non-Errors.
1383//
1384/////////////////////////////////////////////////////////////////////////////////
1385
Jamie Madill5c097022014-08-20 16:38:32 -04001386const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1387 const TString *name,
1388 const TSymbol *symbol)
1389{
1390 const TVariable *variable = NULL;
1391
1392 if (!symbol)
1393 {
1394 error(location, "undeclared identifier", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001395 }
1396 else if (!symbol->isVariable())
1397 {
1398 error(location, "variable expected", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001399 }
1400 else
1401 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001402 variable = static_cast<const TVariable *>(symbol);
Jamie Madill5c097022014-08-20 16:38:32 -04001403
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001404 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
Olli Etuaho383b7912016-08-05 11:22:59 +03001405 !variable->getExtension().empty())
Jamie Madill5c097022014-08-20 16:38:32 -04001406 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001407 checkCanUseExtension(location, variable->getExtension());
Jamie Madill5c097022014-08-20 16:38:32 -04001408 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001409
1410 // Reject shaders using both gl_FragData and gl_FragColor
1411 TQualifier qualifier = variable->getType().getQualifier();
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001412 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001413 {
1414 mUsesFragData = true;
1415 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001416 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001417 {
1418 mUsesFragColor = true;
1419 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001420 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1421 {
1422 mUsesSecondaryOutputs = true;
1423 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001424
1425 // This validation is not quite correct - it's only an error to write to
1426 // both FragData and FragColor. For simplicity, and because users shouldn't
1427 // be rewarded for reading from undefined varaibles, return an error
1428 // if they are both referenced, rather than assigned.
1429 if (mUsesFragData && mUsesFragColor)
1430 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001431 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1432 if (mUsesSecondaryOutputs)
1433 {
1434 errorMessage =
1435 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1436 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1437 }
1438 error(location, errorMessage, name->c_str());
Jamie Madill14e95b32015-05-07 10:10:41 -04001439 }
Martin Radevb0883602016-08-04 17:48:58 +03001440
1441 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1442 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1443 qualifier == EvqWorkGroupSize)
1444 {
1445 error(location,
1446 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1447 "gl_WorkGroupSize");
1448 }
Jamie Madill5c097022014-08-20 16:38:32 -04001449 }
1450
1451 if (!variable)
1452 {
1453 TType type(EbtFloat, EbpUndefined);
1454 TVariable *fakeVariable = new TVariable(name, type);
1455 symbolTable.declare(fakeVariable);
1456 variable = fakeVariable;
1457 }
1458
1459 return variable;
1460}
1461
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001462TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1463 const TString *name,
1464 const TSymbol *symbol)
1465{
1466 const TVariable *variable = getNamedVariable(location, name, symbol);
1467
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001468 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001469 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001470 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001471 return intermediate.addConstantUnion(constArray, variable->getType(), location);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001472 }
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001473 else if (variable->getType().getQualifier() == EvqWorkGroupSize &&
1474 mComputeShaderLocalSizeDeclared)
1475 {
1476 // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
1477 // needs to be added to the AST as a constant and not as a symbol.
1478 sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
1479 TConstantUnion *constArray = new TConstantUnion[3];
1480 for (size_t i = 0; i < 3; ++i)
1481 {
1482 constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
1483 }
1484
1485 ASSERT(variable->getType().getBasicType() == EbtUInt);
1486 ASSERT(variable->getType().getObjectSize() == 3);
1487
1488 TType type(variable->getType());
1489 type.setQualifier(EvqConst);
1490 return intermediate.addConstantUnion(constArray, type, location);
1491 }
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001492 else
1493 {
1494 return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
1495 variable->getType(), location);
1496 }
1497}
1498
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001499//
1500// Look up a function name in the symbol table, and make sure it is a function.
1501//
1502// Return the function symbol if found, otherwise 0.
1503//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001504const TFunction *TParseContext::findFunction(const TSourceLoc &line,
1505 TFunction *call,
1506 int inputShaderVersion,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301507 bool *builtIn)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001508{
alokp@chromium.org0a576182010-08-09 17:16:27 +00001509 // First find by unmangled name to check whether the function name has been
1510 // hidden by a variable name or struct typename.
Nicolas Capensd4a9b8d2013-07-18 11:01:22 -04001511 // If a function is found, check for one with a matching argument list.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301512 const TSymbol *symbol = symbolTable.find(call->getName(), inputShaderVersion, builtIn);
1513 if (symbol == 0 || symbol->isFunction())
1514 {
Austin Kinross3ae64652015-01-26 15:51:39 -08001515 symbol = symbolTable.find(call->getMangledName(), inputShaderVersion, builtIn);
alokp@chromium.org0a576182010-08-09 17:16:27 +00001516 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001517
Arun Patole7e7e68d2015-05-22 12:02:25 +05301518 if (symbol == 0)
1519 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001520 error(line, "no matching overloaded function found", call->getName().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001521 return 0;
1522 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001523
Arun Patole7e7e68d2015-05-22 12:02:25 +05301524 if (!symbol->isFunction())
1525 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001526 error(line, "function name expected", call->getName().c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001527 return 0;
1528 }
alokp@chromium.org0a576182010-08-09 17:16:27 +00001529
Jamie Madillb98c3a82015-07-23 14:26:04 -04001530 return static_cast<const TFunction *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001531}
1532
1533//
1534// Initializers show up in several places in the grammar. Have one set of
1535// code to handle them here.
1536//
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001537// Returns true on error, false if no error
1538//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001539bool TParseContext::executeInitializer(const TSourceLoc &line,
1540 const TString &identifier,
1541 const TPublicType &pType,
1542 TIntermTyped *initializer,
Olli Etuaho13389b62016-10-16 11:48:18 +01001543 TIntermBinary **initNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001544{
Olli Etuaho13389b62016-10-16 11:48:18 +01001545 ASSERT(initNode != nullptr);
1546 ASSERT(*initNode == nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001547 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001548
Olli Etuaho2935c582015-04-08 14:32:06 +03001549 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001550 if (type.isUnsizedArray())
1551 {
Olli Etuaho02bd82c2016-11-03 10:29:43 +00001552 // We have not checked yet whether the initializer actually is an array or not.
1553 if (initializer->isArray())
1554 {
1555 type.setArraySize(initializer->getArraySize());
1556 }
1557 else
1558 {
1559 // Having a non-array initializer for an unsized array will result in an error later,
1560 // so we don't generate an error message here.
1561 type.setArraySize(1u);
1562 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03001563 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001564 if (!declareVariable(line, identifier, type, &variable))
1565 {
1566 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001567 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001568
Olli Etuahob0c645e2015-05-12 14:25:36 +03001569 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001570 if (symbolTable.atGlobalLevel() &&
1571 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001572 {
1573 // Error message does not completely match behavior with ESSL 1.00, but
1574 // we want to steer developers towards only using constant expressions.
1575 error(line, "global variable initializers must be constant expressions", "=");
1576 return true;
1577 }
1578 if (globalInitWarning)
1579 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001580 warning(
1581 line,
1582 "global variable initializers should be constant expressions "
1583 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1584 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001585 }
1586
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001587 //
1588 // identifier must be of type constant, a global, or a temporary
1589 //
1590 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301591 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1592 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001593 error(line, " cannot initialize this type of qualifier ",
1594 variable->getType().getQualifierString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001595 return true;
1596 }
1597 //
1598 // test for and propagate constant
1599 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001600
Arun Patole7e7e68d2015-05-22 12:02:25 +05301601 if (qualifier == EvqConst)
1602 {
1603 if (qualifier != initializer->getType().getQualifier())
1604 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00001605 std::stringstream extraInfoStream;
1606 extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
1607 std::string extraInfo = extraInfoStream.str();
1608 error(line, " assigning non-constant to", "=", extraInfo.c_str());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001609 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001610 return true;
1611 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301612 if (type != initializer->getType())
1613 {
1614 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001615 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001616 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001617 return true;
1618 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001619
1620 // Save the constant folded value to the variable if possible. For example array
1621 // initializers are not folded, since that way copying the array literal to multiple places
1622 // in the shader is avoided.
1623 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1624 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301625 if (initializer->getAsConstantUnion())
1626 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001627 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuaho13389b62016-10-16 11:48:18 +01001628 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001629 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301630 }
1631 else if (initializer->getAsSymbolNode())
1632 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001633 const TSymbol *symbol =
1634 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1635 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001636
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001637 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001638 if (constArray)
1639 {
1640 variable->shareConstPointer(constArray);
Olli Etuaho13389b62016-10-16 11:48:18 +01001641 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001642 return false;
1643 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001644 }
1645 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001646
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001647 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1648 variable->getUniqueId(), variable->getName(), variable->getType(), line);
Olli Etuaho13389b62016-10-16 11:48:18 +01001649 *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1650 if (*initNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001651 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001652 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1653 return true;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001654 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001655
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001656 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001657}
1658
Olli Etuaho0e3aee32016-10-27 12:56:38 +01001659void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
1660{
1661 checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
1662 typeSpecifier->getBasicType());
1663
1664 if (mShaderVersion < 300 && typeSpecifier->array)
1665 {
1666 error(typeSpecifier->getLine(), "not supported", "first-class array");
1667 typeSpecifier->clearArrayness();
1668 }
1669}
1670
Martin Radev70866b82016-07-22 15:27:42 +03001671TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301672 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001673{
Olli Etuaho613b9592016-09-05 12:05:53 +03001674 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001675
Martin Radev70866b82016-07-22 15:27:42 +03001676 TPublicType returnType = typeSpecifier;
1677 returnType.qualifier = typeQualifier.qualifier;
1678 returnType.invariant = typeQualifier.invariant;
1679 returnType.layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03001680 returnType.memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03001681 returnType.precision = typeSpecifier.precision;
1682
1683 if (typeQualifier.precision != EbpUndefined)
1684 {
1685 returnType.precision = typeQualifier.precision;
1686 }
1687
Martin Radev4a9cd802016-09-01 16:51:51 +03001688 checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
1689 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03001690
Martin Radev4a9cd802016-09-01 16:51:51 +03001691 checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
1692 typeSpecifier.getLine());
Martin Radev70866b82016-07-22 15:27:42 +03001693
Martin Radev4a9cd802016-09-01 16:51:51 +03001694 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001695
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001696 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001697 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001698 if (typeSpecifier.array)
1699 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001700 error(typeSpecifier.getLine(), "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001701 returnType.clearArrayness();
1702 }
1703
Martin Radev70866b82016-07-22 15:27:42 +03001704 if (returnType.qualifier == EvqAttribute &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001705 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001706 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001707 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001708 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001709 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001710
Martin Radev70866b82016-07-22 15:27:42 +03001711 if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001712 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001713 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001714 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001715 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001716 }
1717 }
1718 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001719 {
Martin Radev70866b82016-07-22 15:27:42 +03001720 if (!returnType.layoutQualifier.isEmpty())
Olli Etuahoabb0c382015-07-13 12:01:12 +03001721 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001722 checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03001723 }
Martin Radev70866b82016-07-22 15:27:42 +03001724 if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
1725 returnType.qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001726 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001727 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
1728 typeSpecifier.getLine());
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001729 }
Martin Radev70866b82016-07-22 15:27:42 +03001730 if (returnType.qualifier == EvqComputeIn)
Martin Radev802abe02016-08-04 17:48:32 +03001731 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001732 error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
Martin Radev802abe02016-08-04 17:48:32 +03001733 "in");
Martin Radev802abe02016-08-04 17:48:32 +03001734 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001735 }
1736
1737 return returnType;
1738}
1739
Olli Etuaho856c4972016-08-08 11:38:39 +03001740void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1741 const TPublicType &type,
1742 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03001743{
1744 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
Martin Radev4a9cd802016-09-01 16:51:51 +03001745 if (type.getBasicType() == EbtBool)
Olli Etuahocc36b982015-07-10 14:14:18 +03001746 {
1747 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001748 }
1749
1750 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1751 switch (qualifier)
1752 {
1753 case EvqVertexIn:
1754 // ESSL 3.00 section 4.3.4
1755 if (type.array)
1756 {
1757 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001758 }
1759 // Vertex inputs with a struct type are disallowed in singleDeclarationErrorCheck
1760 return;
1761 case EvqFragmentOut:
1762 // ESSL 3.00 section 4.3.6
Martin Radev4a9cd802016-09-01 16:51:51 +03001763 if (type.typeSpecifierNonArray.isMatrix())
Olli Etuahocc36b982015-07-10 14:14:18 +03001764 {
1765 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001766 }
1767 // Fragment outputs with a struct type are disallowed in singleDeclarationErrorCheck
1768 return;
1769 default:
1770 break;
1771 }
1772
1773 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1774 // restrictions.
1775 bool typeContainsIntegers =
Martin Radev4a9cd802016-09-01 16:51:51 +03001776 (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
1777 type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
Olli Etuahocc36b982015-07-10 14:14:18 +03001778 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1779 {
1780 error(qualifierLocation, "must use 'flat' interpolation here",
1781 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001782 }
1783
Martin Radev4a9cd802016-09-01 16:51:51 +03001784 if (type.getBasicType() == EbtStruct)
Olli Etuahocc36b982015-07-10 14:14:18 +03001785 {
1786 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1787 // These restrictions are only implied by the ESSL 3.00 spec, but
1788 // the ESSL 3.10 spec lists these restrictions explicitly.
1789 if (type.array)
1790 {
1791 error(qualifierLocation, "cannot be an array of structures",
1792 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001793 }
1794 if (type.isStructureContainingArrays())
1795 {
1796 error(qualifierLocation, "cannot be a structure containing an array",
1797 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001798 }
1799 if (type.isStructureContainingType(EbtStruct))
1800 {
1801 error(qualifierLocation, "cannot be a structure containing a structure",
1802 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001803 }
1804 if (type.isStructureContainingType(EbtBool))
1805 {
1806 error(qualifierLocation, "cannot be a structure containing a bool",
1807 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001808 }
1809 }
1810}
1811
Martin Radev2cc85b32016-08-05 16:22:53 +03001812void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
1813{
1814 if (qualifier.getType() == QtStorage)
1815 {
1816 const TStorageQualifierWrapper &storageQualifier =
1817 static_cast<const TStorageQualifierWrapper &>(qualifier);
1818 if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
1819 !symbolTable.atGlobalLevel())
1820 {
1821 error(storageQualifier.getLine(),
1822 "Local variables can only use the const storage qualifier.",
1823 storageQualifier.getQualifierString().c_str());
1824 }
1825 }
1826}
1827
1828bool TParseContext::checkIsMemoryQualifierNotSpecified(const TMemoryQualifier &memoryQualifier,
1829 const TSourceLoc &location)
1830{
1831 if (memoryQualifier.readonly)
1832 {
1833 error(location, "Only allowed with images.", "readonly");
1834 return false;
1835 }
1836 if (memoryQualifier.writeonly)
1837 {
1838 error(location, "Only allowed with images.", "writeonly");
1839 return false;
1840 }
Martin Radev049edfa2016-11-11 14:35:37 +02001841 if (memoryQualifier.coherent)
1842 {
1843 error(location, "Only allowed with images.", "coherent");
1844 return false;
1845 }
1846 if (memoryQualifier.restrictQualifier)
1847 {
1848 error(location, "Only allowed with images.", "restrict");
1849 return false;
1850 }
1851 if (memoryQualifier.volatileQualifier)
1852 {
1853 error(location, "Only allowed with images.", "volatile");
1854 return false;
1855 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001856 return true;
1857}
1858
Olli Etuaho13389b62016-10-16 11:48:18 +01001859TIntermDeclaration *TParseContext::parseSingleDeclaration(
1860 TPublicType &publicType,
1861 const TSourceLoc &identifierOrTypeLocation,
1862 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04001863{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001864 TType type(publicType);
1865 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
1866 mDirectiveHandler.pragma().stdgl.invariantAll)
1867 {
1868 TQualifier qualifier = type.getQualifier();
1869
1870 // The directive handler has already taken care of rejecting invalid uses of this pragma
1871 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
1872 // affected variable declarations:
1873 //
1874 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
1875 // elsewhere, in TranslatorGLSL.)
1876 //
1877 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
1878 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
1879 // the way this is currently implemented we have to enable this compiler option before
1880 // parsing the shader and determining the shading language version it uses. If this were
1881 // implemented as a post-pass, the workaround could be more targeted.
1882 //
1883 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
1884 // the specification, but there are desktop OpenGL drivers that expect that this is the
1885 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
1886 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
1887 {
1888 type.setInvariant(true);
1889 }
1890 }
1891
1892 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001893
Olli Etuahobab4c082015-04-24 16:38:49 +03001894 bool emptyDeclaration = (identifier == "");
Olli Etuahofa33d582015-04-09 14:33:12 +03001895
Olli Etuahobab4c082015-04-24 16:38:49 +03001896 mDeferredSingleDeclarationErrorCheck = emptyDeclaration;
1897
Olli Etuaho13389b62016-10-16 11:48:18 +01001898 TIntermDeclaration *declaration = new TIntermDeclaration();
1899 declaration->setLine(identifierOrTypeLocation);
1900
Olli Etuahobab4c082015-04-24 16:38:49 +03001901 if (emptyDeclaration)
1902 {
1903 if (publicType.isUnsizedArray())
1904 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001905 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1906 // error. It is assumed that this applies to empty declarations as well.
1907 error(identifierOrTypeLocation, "empty array declaration needs to specify a size",
1908 identifier.c_str());
Olli Etuahobab4c082015-04-24 16:38:49 +03001909 }
1910 }
1911 else
Jamie Madill60ed9812013-06-06 11:56:46 -04001912 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001913 singleDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001914
Olli Etuaho856c4972016-08-08 11:38:39 +03001915 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001916
Olli Etuaho2935c582015-04-08 14:32:06 +03001917 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001918 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001919
1920 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01001921 {
Jamie Madill60ed9812013-06-06 11:56:46 -04001922 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01001923 }
Jamie Madill60ed9812013-06-06 11:56:46 -04001924 }
1925
Olli Etuaho13389b62016-10-16 11:48:18 +01001926 // We append the symbol even if the declaration is empty, mainly because of struct declarations
1927 // that may just declare a type.
1928 declaration->appendDeclarator(symbol);
1929
1930 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04001931}
1932
Olli Etuaho13389b62016-10-16 11:48:18 +01001933TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1934 const TSourceLoc &identifierLocation,
1935 const TString &identifier,
1936 const TSourceLoc &indexLocation,
1937 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04001938{
Olli Etuahofa33d582015-04-09 14:33:12 +03001939 mDeferredSingleDeclarationErrorCheck = false;
1940
Olli Etuaho383b7912016-08-05 11:22:59 +03001941 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001942
Olli Etuaho856c4972016-08-08 11:38:39 +03001943 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001944
Olli Etuaho8a176262016-08-16 14:23:01 +03001945 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001946
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001947 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001948
Olli Etuaho856c4972016-08-08 11:38:39 +03001949 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001950 // Make the type an array even if size check failed.
1951 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1952 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04001953
Olli Etuaho2935c582015-04-08 14:32:06 +03001954 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001955 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001956
Olli Etuaho13389b62016-10-16 11:48:18 +01001957 TIntermDeclaration *declaration = new TIntermDeclaration();
1958 declaration->setLine(identifierLocation);
1959
Olli Etuahoe7847b02015-03-16 11:56:12 +02001960 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001961 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01001962 {
Jamie Madill60ed9812013-06-06 11:56:46 -04001963 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01001964 declaration->appendDeclarator(symbol);
1965 }
Jamie Madill60ed9812013-06-06 11:56:46 -04001966
Olli Etuaho13389b62016-10-16 11:48:18 +01001967 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04001968}
1969
Olli Etuaho13389b62016-10-16 11:48:18 +01001970TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
1971 const TSourceLoc &identifierLocation,
1972 const TString &identifier,
1973 const TSourceLoc &initLocation,
1974 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04001975{
Olli Etuahofa33d582015-04-09 14:33:12 +03001976 mDeferredSingleDeclarationErrorCheck = false;
1977
Olli Etuaho383b7912016-08-05 11:22:59 +03001978 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001979
Olli Etuaho13389b62016-10-16 11:48:18 +01001980 TIntermDeclaration *declaration = new TIntermDeclaration();
1981 declaration->setLine(identifierLocation);
1982
1983 TIntermBinary *initNode = nullptr;
1984 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04001985 {
Olli Etuaho13389b62016-10-16 11:48:18 +01001986 if (initNode)
1987 {
1988 declaration->appendDeclarator(initNode);
1989 }
Jamie Madill60ed9812013-06-06 11:56:46 -04001990 }
Olli Etuaho13389b62016-10-16 11:48:18 +01001991 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04001992}
1993
Olli Etuaho13389b62016-10-16 11:48:18 +01001994TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
Jamie Madillb98c3a82015-07-23 14:26:04 -04001995 TPublicType &publicType,
1996 const TSourceLoc &identifierLocation,
1997 const TString &identifier,
1998 const TSourceLoc &indexLocation,
1999 TIntermTyped *indexExpression,
2000 const TSourceLoc &initLocation,
2001 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002002{
2003 mDeferredSingleDeclarationErrorCheck = false;
2004
Olli Etuaho383b7912016-08-05 11:22:59 +03002005 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002006
Olli Etuaho8a176262016-08-16 14:23:01 +03002007 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002008
2009 TPublicType arrayType(publicType);
2010
Olli Etuaho856c4972016-08-08 11:38:39 +03002011 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002012 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2013 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002014 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002015 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002016 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002017 }
2018 // Make the type an array even if size check failed.
2019 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2020 arrayType.setArraySize(size);
2021
Olli Etuaho13389b62016-10-16 11:48:18 +01002022 TIntermDeclaration *declaration = new TIntermDeclaration();
2023 declaration->setLine(identifierLocation);
2024
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002025 // initNode will correspond to the whole of "type b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002026 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002027 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2028 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002029 if (initNode)
2030 {
2031 declaration->appendDeclarator(initNode);
2032 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002033 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002034
2035 return declaration;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002036}
2037
Martin Radev70866b82016-07-22 15:27:42 +03002038TIntermAggregate *TParseContext::parseInvariantDeclaration(
2039 const TTypeQualifierBuilder &typeQualifierBuilder,
2040 const TSourceLoc &identifierLoc,
2041 const TString *identifier,
2042 const TSymbol *symbol)
Jamie Madill47e3ec02014-08-20 16:38:33 -04002043{
Olli Etuaho613b9592016-09-05 12:05:53 +03002044 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002045
Martin Radev70866b82016-07-22 15:27:42 +03002046 if (!typeQualifier.invariant)
2047 {
2048 error(identifierLoc, "Expected invariant", identifier->c_str());
2049 return nullptr;
2050 }
2051 if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
2052 {
2053 return nullptr;
2054 }
Jamie Madill47e3ec02014-08-20 16:38:33 -04002055 if (!symbol)
2056 {
2057 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002058 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04002059 }
Martin Radev70866b82016-07-22 15:27:42 +03002060 if (!IsQualifierUnspecified(typeQualifier.qualifier))
Jamie Madill47e3ec02014-08-20 16:38:33 -04002061 {
Martin Radev70866b82016-07-22 15:27:42 +03002062 error(identifierLoc, "invariant declaration specifies qualifier",
2063 getQualifierString(typeQualifier.qualifier));
Jamie Madill47e3ec02014-08-20 16:38:33 -04002064 }
Martin Radev70866b82016-07-22 15:27:42 +03002065 if (typeQualifier.precision != EbpUndefined)
2066 {
2067 error(identifierLoc, "invariant declaration specifies precision",
2068 getPrecisionString(typeQualifier.precision));
2069 }
2070 if (!typeQualifier.layoutQualifier.isEmpty())
2071 {
2072 error(identifierLoc, "invariant declaration specifies layout", "'layout'");
2073 }
2074
2075 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
2076 ASSERT(variable);
2077 const TType &type = variable->getType();
2078
2079 checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
2080 typeQualifier.line);
Martin Radev2cc85b32016-08-05 16:22:53 +03002081 checkIsMemoryQualifierNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev70866b82016-07-22 15:27:42 +03002082
2083 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
2084
2085 TIntermSymbol *intermSymbol =
2086 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
2087
Olli Etuaho32db19b2016-10-04 14:43:16 +01002088 TIntermAggregate *aggregate = TIntermediate::MakeAggregate(intermSymbol, identifierLoc);
Martin Radev70866b82016-07-22 15:27:42 +03002089 aggregate->setOp(EOpInvariantDeclaration);
2090 return aggregate;
Jamie Madill47e3ec02014-08-20 16:38:33 -04002091}
2092
Olli Etuaho13389b62016-10-16 11:48:18 +01002093void TParseContext::parseDeclarator(TPublicType &publicType,
2094 const TSourceLoc &identifierLocation,
2095 const TString &identifier,
2096 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002097{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002098 // If the declaration starting this declarator list was empty (example: int,), some checks were
2099 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03002100 if (mDeferredSingleDeclarationErrorCheck)
2101 {
Olli Etuaho383b7912016-08-05 11:22:59 +03002102 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03002103 mDeferredSingleDeclarationErrorCheck = false;
2104 }
2105
Olli Etuaho856c4972016-08-08 11:38:39 +03002106 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002107
Olli Etuaho856c4972016-08-08 11:38:39 +03002108 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002109
Olli Etuaho2935c582015-04-08 14:32:06 +03002110 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002111 declareVariable(identifierLocation, identifier, TType(publicType), &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002112
Jamie Madillb98c3a82015-07-23 14:26:04 -04002113 TIntermSymbol *symbol =
2114 intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002115 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002116 {
Jamie Madill502d66f2013-06-20 11:55:52 -04002117 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002118 declarationOut->appendDeclarator(symbol);
2119 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002120}
2121
Olli Etuaho13389b62016-10-16 11:48:18 +01002122void TParseContext::parseArrayDeclarator(TPublicType &publicType,
2123 const TSourceLoc &identifierLocation,
2124 const TString &identifier,
2125 const TSourceLoc &arrayLocation,
2126 TIntermTyped *indexExpression,
2127 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002128{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002129 // If the declaration starting this declarator list was empty (example: int,), some checks were
2130 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03002131 if (mDeferredSingleDeclarationErrorCheck)
2132 {
Olli Etuaho383b7912016-08-05 11:22:59 +03002133 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03002134 mDeferredSingleDeclarationErrorCheck = false;
2135 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002136
Olli Etuaho856c4972016-08-08 11:38:39 +03002137 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002138
Olli Etuaho856c4972016-08-08 11:38:39 +03002139 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002140
Olli Etuaho8a176262016-08-16 14:23:01 +03002141 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04002142 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002143 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03002144 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03002145 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002146
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002147 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002148 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04002149
Jamie Madillb98c3a82015-07-23 14:26:04 -04002150 TIntermSymbol *symbol =
2151 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002152 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002153 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002154
Olli Etuaho13389b62016-10-16 11:48:18 +01002155 declarationOut->appendDeclarator(symbol);
Jamie Madill502d66f2013-06-20 11:55:52 -04002156 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002157}
2158
Olli Etuaho13389b62016-10-16 11:48:18 +01002159void TParseContext::parseInitDeclarator(const TPublicType &publicType,
2160 const TSourceLoc &identifierLocation,
2161 const TString &identifier,
2162 const TSourceLoc &initLocation,
2163 TIntermTyped *initializer,
2164 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002165{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002166 // If the declaration starting this declarator list was empty (example: int,), some checks were
2167 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03002168 if (mDeferredSingleDeclarationErrorCheck)
2169 {
Olli Etuaho383b7912016-08-05 11:22:59 +03002170 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03002171 mDeferredSingleDeclarationErrorCheck = false;
2172 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002173
Olli Etuaho856c4972016-08-08 11:38:39 +03002174 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002175
Olli Etuaho13389b62016-10-16 11:48:18 +01002176 TIntermBinary *initNode = nullptr;
2177 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04002178 {
2179 //
2180 // build the intermediate representation
2181 //
Olli Etuaho13389b62016-10-16 11:48:18 +01002182 if (initNode)
Jamie Madill502d66f2013-06-20 11:55:52 -04002183 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002184 declarationOut->appendDeclarator(initNode);
Jamie Madill502d66f2013-06-20 11:55:52 -04002185 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002186 }
2187}
2188
Olli Etuaho13389b62016-10-16 11:48:18 +01002189void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
2190 const TSourceLoc &identifierLocation,
2191 const TString &identifier,
2192 const TSourceLoc &indexLocation,
2193 TIntermTyped *indexExpression,
2194 const TSourceLoc &initLocation,
2195 TIntermTyped *initializer,
2196 TIntermDeclaration *declarationOut)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002197{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002198 // If the declaration starting this declarator list was empty (example: int,), some checks were
2199 // not performed.
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002200 if (mDeferredSingleDeclarationErrorCheck)
2201 {
Olli Etuaho383b7912016-08-05 11:22:59 +03002202 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002203 mDeferredSingleDeclarationErrorCheck = false;
2204 }
2205
Olli Etuaho856c4972016-08-08 11:38:39 +03002206 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002207
Olli Etuaho8a176262016-08-16 14:23:01 +03002208 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002209
2210 TPublicType arrayType(publicType);
2211
Olli Etuaho856c4972016-08-08 11:38:39 +03002212 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002213 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2214 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002215 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002216 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002217 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002218 }
2219 // Make the type an array even if size check failed.
2220 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2221 arrayType.setArraySize(size);
2222
2223 // initNode will correspond to the whole of "b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002224 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002225 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2226 {
2227 if (initNode)
2228 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002229 declarationOut->appendDeclarator(initNode);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002230 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002231 }
2232}
2233
Martin Radev70866b82016-07-22 15:27:42 +03002234void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
Jamie Madilla295edf2013-06-06 11:56:48 -04002235{
Olli Etuaho613b9592016-09-05 12:05:53 +03002236 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
Jamie Madilla295edf2013-06-06 11:56:48 -04002237 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04002238
Martin Radev70866b82016-07-22 15:27:42 +03002239 checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
2240 typeQualifier.line);
2241
Jamie Madillc2128ff2016-07-04 10:26:17 -04002242 // It should never be the case, but some strange parser errors can send us here.
2243 if (layoutQualifier.isEmpty())
2244 {
2245 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04002246 return;
2247 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002248
Martin Radev802abe02016-08-04 17:48:32 +03002249 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04002250 {
Martin Radev802abe02016-08-04 17:48:32 +03002251 error(typeQualifier.line, "invalid combination:", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04002252 return;
2253 }
2254
Martin Radev2cc85b32016-08-05 16:22:53 +03002255 checkIsMemoryQualifierNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
2256
2257 checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
2258
Martin Radev802abe02016-08-04 17:48:32 +03002259 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04002260 {
Martin Radev802abe02016-08-04 17:48:32 +03002261 if (mComputeShaderLocalSizeDeclared &&
2262 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
2263 {
2264 error(typeQualifier.line, "Work group size does not match the previous declaration",
2265 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002266 return;
2267 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002268
Martin Radev802abe02016-08-04 17:48:32 +03002269 if (mShaderVersion < 310)
2270 {
2271 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002272 return;
2273 }
Jamie Madill099c0f32013-06-20 11:55:52 -04002274
Martin Radev4c4c8e72016-08-04 12:25:34 +03002275 if (!layoutQualifier.localSize.isAnyValueSet())
Martin Radev802abe02016-08-04 17:48:32 +03002276 {
2277 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002278 return;
2279 }
2280
2281 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
2282 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
2283
2284 const TConstantUnion *maxComputeWorkGroupSizeData =
2285 maxComputeWorkGroupSize->getConstPointer();
2286
2287 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
2288 {
2289 if (layoutQualifier.localSize[i] != -1)
2290 {
2291 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
2292 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
2293 if (mComputeShaderLocalSize[i] < 1 ||
2294 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
2295 {
2296 std::stringstream errorMessageStream;
2297 errorMessageStream << "Value must be at least 1 and no greater than "
2298 << maxComputeWorkGroupSizeValue;
2299 const std::string &errorMessage = errorMessageStream.str();
2300
Martin Radev4c4c8e72016-08-04 12:25:34 +03002301 error(typeQualifier.line, "invalid value:", getWorkGroupSizeString(i),
Martin Radev802abe02016-08-04 17:48:32 +03002302 errorMessage.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03002303 return;
2304 }
2305 }
2306 }
2307
2308 mComputeShaderLocalSizeDeclared = true;
2309 }
2310 else
Jamie Madill1566ef72013-06-20 11:55:54 -04002311 {
Martin Radev802abe02016-08-04 17:48:32 +03002312
Olli Etuaho8a176262016-08-16 14:23:01 +03002313 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03002314 {
Martin Radev802abe02016-08-04 17:48:32 +03002315 return;
2316 }
2317
2318 if (typeQualifier.qualifier != EvqUniform)
2319 {
2320 error(typeQualifier.line, "invalid qualifier:",
2321 getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
Martin Radev802abe02016-08-04 17:48:32 +03002322 return;
2323 }
2324
2325 if (mShaderVersion < 300)
2326 {
2327 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
2328 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002329 return;
2330 }
2331
Olli Etuaho856c4972016-08-08 11:38:39 +03002332 checkLocationIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002333
2334 if (layoutQualifier.matrixPacking != EmpUnspecified)
2335 {
2336 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
2337 }
2338
2339 if (layoutQualifier.blockStorage != EbsUnspecified)
2340 {
2341 mDefaultBlockStorage = layoutQualifier.blockStorage;
2342 }
Jamie Madill1566ef72013-06-20 11:55:54 -04002343 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002344}
2345
Olli Etuaho476197f2016-10-11 13:59:08 +01002346TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &parsedFunction,
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002347 const TSourceLoc &location)
2348{
Olli Etuaho476197f2016-10-11 13:59:08 +01002349 // Note: function found from the symbol table could be the same as parsedFunction if this is the
2350 // first declaration. Either way the instance in the symbol table is used to track whether the
2351 // function is declared multiple times.
2352 TFunction *function = static_cast<TFunction *>(
2353 symbolTable.find(parsedFunction.getMangledName(), getShaderVersion()));
2354 if (function->hasPrototypeDeclaration() && mShaderVersion == 100)
Olli Etuaho5d653182016-01-04 14:43:28 +02002355 {
2356 // ESSL 1.00.17 section 4.2.7.
2357 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
2358 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02002359 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002360 function->setHasPrototypeDeclaration();
Olli Etuaho5d653182016-01-04 14:43:28 +02002361
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002362 TIntermAggregate *prototype = new TIntermAggregate;
Olli Etuaho476197f2016-10-11 13:59:08 +01002363 // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
2364 // point to the data that already exists in the symbol table.
2365 prototype->setType(function->getReturnType());
Olli Etuahobd674552016-10-06 13:28:42 +01002366 prototype->getFunctionSymbolInfo()->setFromFunction(*function);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002367
Olli Etuaho476197f2016-10-11 13:59:08 +01002368 for (size_t i = 0; i < function->getParamCount(); i++)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002369 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002370 const TConstParameter &param = function->getParam(i);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002371 if (param.name != 0)
2372 {
2373 TVariable variable(param.name, *param.type);
2374
2375 TIntermSymbol *paramSymbol = intermediate.addSymbol(
2376 variable.getUniqueId(), variable.getName(), variable.getType(), location);
2377 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
2378 }
2379 else
2380 {
2381 TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002382 prototype = intermediate.growAggregate(prototype, paramSymbol, location);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002383 }
2384 }
2385
2386 prototype->setOp(EOpPrototype);
2387
2388 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002389
2390 if (!symbolTable.atGlobalLevel())
2391 {
2392 // ESSL 3.00.4 section 4.2.4.
2393 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002394 }
2395
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002396 return prototype;
2397}
2398
Olli Etuaho336b1472016-10-05 16:37:55 +01002399TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
2400 const TFunction &function,
2401 TIntermAggregate *functionParameters,
2402 TIntermBlock *functionBody,
2403 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002404{
Olli Etuahof51fdd22016-10-03 10:03:40 +01002405 // Check that non-void functions have at least one return statement.
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002406 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2407 {
2408 error(location, "function does not return a value:", "", function.getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002409 }
2410
Olli Etuahof51fdd22016-10-03 10:03:40 +01002411 if (functionBody == nullptr)
2412 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01002413 functionBody = new TIntermBlock();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002414 functionBody->setLine(location);
2415 }
Olli Etuaho336b1472016-10-05 16:37:55 +01002416 TIntermFunctionDefinition *functionNode =
2417 new TIntermFunctionDefinition(function.getReturnType(), functionParameters, functionBody);
2418 functionNode->setLine(location);
Olli Etuahof51fdd22016-10-03 10:03:40 +01002419
Olli Etuahobd674552016-10-06 13:28:42 +01002420 functionNode->getFunctionSymbolInfo()->setFromFunction(function);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002421
2422 symbolTable.pop();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002423 return functionNode;
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002424}
2425
Olli Etuaho476197f2016-10-11 13:59:08 +01002426void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
2427 TFunction **function,
2428 TIntermAggregate **aggregateOut)
Jamie Madill185fb402015-06-12 15:48:48 -04002429{
Olli Etuaho476197f2016-10-11 13:59:08 +01002430 ASSERT(function);
2431 ASSERT(*function);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002432 const TSymbol *builtIn =
Olli Etuaho476197f2016-10-11 13:59:08 +01002433 symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002434
2435 if (builtIn)
2436 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002437 error(location, "built-in functions cannot be redefined", (*function)->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002438 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002439 else
Jamie Madill185fb402015-06-12 15:48:48 -04002440 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002441 TFunction *prevDec = static_cast<TFunction *>(
2442 symbolTable.find((*function)->getMangledName(), getShaderVersion()));
2443
2444 // Note: 'prevDec' could be 'function' if this is the first time we've seen function as it
2445 // would have just been put in the symbol table. Otherwise, we're looking up an earlier
2446 // occurance.
2447 if (*function != prevDec)
2448 {
2449 // Swap the parameters of the previous declaration to the parameters of the function
2450 // definition (parameter names may differ).
2451 prevDec->swapParameters(**function);
2452
2453 // The function definition will share the same symbol as any previous declaration.
2454 *function = prevDec;
2455 }
2456
2457 if ((*function)->isDefined())
2458 {
2459 error(location, "function already has a body", (*function)->getName().c_str());
2460 }
2461
2462 (*function)->setDefined();
Jamie Madill185fb402015-06-12 15:48:48 -04002463 }
Jamie Madill185fb402015-06-12 15:48:48 -04002464
2465 // Raise error message if main function takes any parameters or return anything other than void
Olli Etuaho476197f2016-10-11 13:59:08 +01002466 if ((*function)->getName() == "main")
Jamie Madill185fb402015-06-12 15:48:48 -04002467 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002468 if ((*function)->getParamCount() > 0)
Jamie Madill185fb402015-06-12 15:48:48 -04002469 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002470 error(location, "function cannot take any parameter(s)",
2471 (*function)->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002472 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002473 if ((*function)->getReturnType().getBasicType() != EbtVoid)
Jamie Madill185fb402015-06-12 15:48:48 -04002474 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002475 error(location, "", (*function)->getReturnType().getBasicString(),
Jamie Madillb98c3a82015-07-23 14:26:04 -04002476 "main function cannot return a value");
Jamie Madill185fb402015-06-12 15:48:48 -04002477 }
2478 }
2479
2480 //
2481 // Remember the return type for later checking for RETURN statements.
2482 //
Olli Etuaho476197f2016-10-11 13:59:08 +01002483 mCurrentFunctionType = &((*function)->getReturnType());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002484 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002485
2486 //
2487 // Insert parameters into the symbol table.
2488 // If the parameter has no name, it's not an error, just don't insert it
2489 // (could be used for unused args).
2490 //
2491 // Also, accumulate the list of parameters into the HIL, so lower level code
2492 // knows where to find parameters.
2493 //
2494 TIntermAggregate *paramNodes = new TIntermAggregate;
Olli Etuaho476197f2016-10-11 13:59:08 +01002495 for (size_t i = 0; i < (*function)->getParamCount(); i++)
Jamie Madill185fb402015-06-12 15:48:48 -04002496 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002497 const TConstParameter &param = (*function)->getParam(i);
Jamie Madill185fb402015-06-12 15:48:48 -04002498 if (param.name != 0)
2499 {
2500 TVariable *variable = new TVariable(param.name, *param.type);
2501 //
2502 // Insert the parameters with name in the symbol table.
2503 //
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002504 if (!symbolTable.declare(variable))
2505 {
Jamie Madill185fb402015-06-12 15:48:48 -04002506 error(location, "redefinition", variable->getName().c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -04002507 paramNodes = intermediate.growAggregate(
2508 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
2509 continue;
Jamie Madill185fb402015-06-12 15:48:48 -04002510 }
2511
2512 //
2513 // Add the parameter to the HIL
2514 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002515 TIntermSymbol *symbol = intermediate.addSymbol(
2516 variable->getUniqueId(), variable->getName(), variable->getType(), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002517
2518 paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
2519 }
2520 else
2521 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002522 paramNodes = intermediate.growAggregate(
2523 paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
Jamie Madill185fb402015-06-12 15:48:48 -04002524 }
2525 }
2526 intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
2527 *aggregateOut = paramNodes;
2528 setLoopNestingLevel(0);
2529}
2530
Jamie Madillb98c3a82015-07-23 14:26:04 -04002531TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002532{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002533 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002534 // We don't know at this point whether this is a function definition or a prototype.
2535 // The definition production code will check for redefinitions.
2536 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002537 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002538 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2539 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002540 //
2541 TFunction *prevDec =
2542 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302543
2544 if (getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltIn(function->getName().c_str()))
2545 {
2546 // With ESSL 3.00, names of built-in functions cannot be redeclared as functions.
2547 // Therefore overloading or redefining builtin functions is an error.
2548 error(location, "Name of a built-in function cannot be redeclared as function",
2549 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302550 }
2551 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002552 {
2553 if (prevDec->getReturnType() != function->getReturnType())
2554 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002555 error(location, "function must have the same return type in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002556 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002557 }
2558 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2559 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002560 if (prevDec->getParam(i).type->getQualifier() !=
2561 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002562 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002563 error(location,
2564 "function must have the same parameter qualifiers in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002565 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002566 }
2567 }
2568 }
2569
2570 //
2571 // Check for previously declared variables using the same name.
2572 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002573 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002574 if (prevSym)
2575 {
2576 if (!prevSym->isFunction())
2577 {
2578 error(location, "redefinition", function->getName().c_str(), "function");
Jamie Madill185fb402015-06-12 15:48:48 -04002579 }
2580 }
2581 else
2582 {
2583 // Insert the unmangled name to detect potential future redefinition as a variable.
Olli Etuaho476197f2016-10-11 13:59:08 +01002584 symbolTable.getOuterLevel()->insertUnmangled(function);
Jamie Madill185fb402015-06-12 15:48:48 -04002585 }
2586
2587 // We're at the inner scope level of the function's arguments and body statement.
2588 // Add the function prototype to the surrounding scope instead.
2589 symbolTable.getOuterLevel()->insert(function);
2590
2591 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002592 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2593 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002594 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2595 //
2596 return function;
2597}
2598
Olli Etuaho9de84a52016-06-14 17:36:01 +03002599TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2600 const TString *name,
2601 const TSourceLoc &location)
2602{
2603 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2604 {
2605 error(location, "no qualifiers allowed for function return",
2606 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002607 }
2608 if (!type.layoutQualifier.isEmpty())
2609 {
2610 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002611 }
Martin Radev2cc85b32016-08-05 16:22:53 +03002612 // make sure a sampler or an image is not involved as well...
Martin Radev4a9cd802016-09-01 16:51:51 +03002613 checkIsNotSampler(location, type.typeSpecifierNonArray,
2614 "samplers can't be function return values");
Martin Radev2cc85b32016-08-05 16:22:53 +03002615 checkIsNotImage(location, type.typeSpecifierNonArray, "images can't be function return values");
Olli Etuahoe29324f2016-06-15 10:58:03 +03002616 if (mShaderVersion < 300)
2617 {
2618 // Array return values are forbidden, but there's also no valid syntax for declaring array
2619 // return values in ESSL 1.00.
2620 ASSERT(type.arraySize == 0 || mDiagnostics.numErrors() > 0);
2621
2622 if (type.isStructureContainingArrays())
2623 {
2624 // ESSL 1.00.17 section 6.1 Function Definitions
2625 error(location, "structures containing arrays can't be function return values",
2626 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002627 }
2628 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002629
2630 // Add the function as a prototype after parsing it (we do not support recursion)
2631 return new TFunction(name, new TType(type));
2632}
2633
Jamie Madill06145232015-05-13 13:10:01 -04002634TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002635{
Jamie Madill06145232015-05-13 13:10:01 -04002636 TPublicType publicType = publicTypeIn;
Martin Radev4a9cd802016-09-01 16:51:51 +03002637 if (publicType.isStructSpecifier())
Olli Etuahobd163f62015-11-13 12:15:38 +02002638 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002639 error(publicType.getLine(), "constructor can't be a structure definition",
2640 getBasicString(publicType.getBasicType()));
Olli Etuahobd163f62015-11-13 12:15:38 +02002641 }
2642
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002643 TOperator op = EOpNull;
Martin Radev4a9cd802016-09-01 16:51:51 +03002644 if (publicType.getUserDef())
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002645 {
2646 op = EOpConstructStruct;
2647 }
2648 else
2649 {
Geoff Lang156d7192016-07-21 16:11:00 -04002650 op = sh::TypeToConstructorOperator(TType(publicType));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002651 if (op == EOpNull)
2652 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002653 error(publicType.getLine(), "cannot construct this type",
2654 getBasicString(publicType.getBasicType()));
2655 publicType.setBasicType(EbtFloat);
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002656 op = EOpConstructFloat;
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002657 }
2658 }
2659
2660 TString tempString;
Dmitry Skiba7f17a502015-06-22 15:08:39 -07002661 const TType *type = new TType(publicType);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002662 return new TFunction(&tempString, type, op);
2663}
2664
Jamie Madillb98c3a82015-07-23 14:26:04 -04002665// This function is used to test for the correctness of the parameters passed to various constructor
2666// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002667//
Olli Etuaho856c4972016-08-08 11:38:39 +03002668// 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 +00002669//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002670TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002671 TOperator op,
2672 TFunction *fnCall,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302673 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002674{
Olli Etuaho856c4972016-08-08 11:38:39 +03002675 TType type = fnCall->getReturnType();
2676 if (type.isUnsizedArray())
2677 {
Olli Etuahobbe9fb52016-11-03 17:16:05 +00002678 if (fnCall->getParamCount() == 0)
2679 {
2680 error(line, "implicitly sized array constructor must have at least one argument", "[]");
2681 type.setArraySize(1u);
2682 return TIntermTyped::CreateZero(type);
2683 }
Olli Etuaho856c4972016-08-08 11:38:39 +03002684 type.setArraySize(static_cast<unsigned int>(fnCall->getParamCount()));
2685 }
2686 bool constType = true;
2687 for (size_t i = 0; i < fnCall->getParamCount(); ++i)
2688 {
2689 const TConstParameter &param = fnCall->getParam(i);
2690 if (param.type->getQualifier() != EvqConst)
2691 constType = false;
2692 }
2693 if (constType)
2694 type.setQualifier(EvqConst);
2695
Olli Etuaho8a176262016-08-16 14:23:01 +03002696 if (!checkConstructorArguments(line, arguments, *fnCall, op, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002697 {
2698 TIntermTyped *dummyNode = intermediate.setAggregateOperator(nullptr, op, line);
2699 dummyNode->setType(type);
2700 return dummyNode;
2701 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002702 TIntermAggregate *constructor = arguments->getAsAggregate();
2703 ASSERT(constructor != nullptr);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002704
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002705 // Turn the argument list itself into a constructor
Olli Etuaho15c2ac32015-11-09 15:51:43 +02002706 constructor->setOp(op);
2707 constructor->setLine(line);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002708 ASSERT(constructor->isConstructor());
2709
2710 // Need to set type before setPrecisionFromChildren() because bool doesn't have precision.
Olli Etuaho856c4972016-08-08 11:38:39 +03002711 constructor->setType(type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002712
Olli Etuaho21203702014-11-13 16:16:21 +02002713 // Structs should not be precision qualified, the individual members may be.
2714 // Built-in types on the other hand should be precision qualified.
2715 if (op != EOpConstructStruct)
2716 {
2717 constructor->setPrecisionFromChildren();
Olli Etuaho856c4972016-08-08 11:38:39 +03002718 type.setPrecision(constructor->getPrecision());
Olli Etuaho21203702014-11-13 16:16:21 +02002719 }
2720
Olli Etuaho856c4972016-08-08 11:38:39 +03002721 constructor->setType(type);
2722
Olli Etuahof119a262016-08-19 15:54:22 +03002723 TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor, &mDiagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002724 if (constConstructor)
2725 {
2726 return constConstructor;
2727 }
2728
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002729 return constructor;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002730}
2731
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002732//
2733// Interface/uniform blocks
2734//
Olli Etuaho13389b62016-10-16 11:48:18 +01002735TIntermDeclaration *TParseContext::addInterfaceBlock(
Martin Radev70866b82016-07-22 15:27:42 +03002736 const TTypeQualifierBuilder &typeQualifierBuilder,
2737 const TSourceLoc &nameLine,
2738 const TString &blockName,
2739 TFieldList *fieldList,
2740 const TString *instanceName,
2741 const TSourceLoc &instanceLine,
2742 TIntermTyped *arrayIndex,
2743 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002744{
Olli Etuaho856c4972016-08-08 11:38:39 +03002745 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002746
Olli Etuaho613b9592016-09-05 12:05:53 +03002747 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03002748
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002749 if (typeQualifier.qualifier != EvqUniform)
2750 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302751 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier),
2752 "interface blocks must be uniform");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002753 }
2754
Martin Radev70866b82016-07-22 15:27:42 +03002755 if (typeQualifier.invariant)
2756 {
2757 error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
2758 }
2759
Martin Radev2cc85b32016-08-05 16:22:53 +03002760 checkIsMemoryQualifierNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
2761
Jamie Madill099c0f32013-06-20 11:55:52 -04002762 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03002763 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04002764
Jamie Madill099c0f32013-06-20 11:55:52 -04002765 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2766 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002767 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002768 }
2769
Jamie Madill1566ef72013-06-20 11:55:54 -04002770 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2771 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002772 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002773 }
2774
Olli Etuaho856c4972016-08-08 11:38:39 +03002775 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002776
Martin Radev2cc85b32016-08-05 16:22:53 +03002777 checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
2778
Arun Patole7e7e68d2015-05-22 12:02:25 +05302779 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2780 if (!symbolTable.declare(blockNameSymbol))
2781 {
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002782 error(nameLine, "redefinition", blockName.c_str(), "interface block name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002783 }
2784
Jamie Madill98493dd2013-07-08 14:39:03 -04002785 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302786 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2787 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002788 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302789 TType *fieldType = field->type();
2790 if (IsSampler(fieldType->getBasicType()))
2791 {
2792 error(field->line(), "unsupported type", fieldType->getBasicString(),
2793 "sampler types are not allowed in interface blocks");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002794 }
2795
Martin Radev2cc85b32016-08-05 16:22:53 +03002796 if (IsImage(fieldType->getBasicType()))
2797 {
2798 error(field->line(), "unsupported type", fieldType->getBasicString(),
2799 "image types are not allowed in interface blocks");
2800 }
2801
Jamie Madill98493dd2013-07-08 14:39:03 -04002802 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002803 switch (qualifier)
2804 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002805 case EvqGlobal:
2806 case EvqUniform:
2807 break;
2808 default:
2809 error(field->line(), "invalid qualifier on interface block member",
2810 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04002811 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002812 }
Jamie Madilla5efff92013-06-06 11:56:47 -04002813
Martin Radev70866b82016-07-22 15:27:42 +03002814 if (fieldType->isInvariant())
2815 {
2816 error(field->line(), "invalid qualifier on interface block member", "invariant");
2817 }
2818
Jamie Madilla5efff92013-06-06 11:56:47 -04002819 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04002820 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03002821 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Jamie Madill099c0f32013-06-20 11:55:52 -04002822
Jamie Madill98493dd2013-07-08 14:39:03 -04002823 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04002824 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002825 error(field->line(), "invalid layout qualifier:",
2826 getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
Jamie Madill1566ef72013-06-20 11:55:54 -04002827 }
2828
Jamie Madill98493dd2013-07-08 14:39:03 -04002829 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04002830 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002831 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002832 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002833 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04002834 {
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002835 warning(field->line(), "extraneous layout qualifier:",
Jamie Madillb98c3a82015-07-23 14:26:04 -04002836 getMatrixPackingString(fieldLayoutQualifier.matrixPacking),
2837 "only has an effect on matrix types");
Jamie Madill099c0f32013-06-20 11:55:52 -04002838 }
2839
Jamie Madill98493dd2013-07-08 14:39:03 -04002840 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002841 }
2842
Jamie Madill98493dd2013-07-08 14:39:03 -04002843 // add array index
Olli Etuaho856c4972016-08-08 11:38:39 +03002844 unsigned int arraySize = 0;
2845 if (arrayIndex != nullptr)
Jamie Madill98493dd2013-07-08 14:39:03 -04002846 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002847 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
Jamie Madill98493dd2013-07-08 14:39:03 -04002848 }
2849
Jamie Madillb98c3a82015-07-23 14:26:04 -04002850 TInterfaceBlock *interfaceBlock =
2851 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2852 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
2853 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002854
2855 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04002856 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002857
Jamie Madill98493dd2013-07-08 14:39:03 -04002858 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002859 {
2860 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04002861 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2862 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002863 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302864 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04002865
2866 // set parent pointer of the field variable
2867 fieldType->setInterfaceBlock(interfaceBlock);
2868
Arun Patole7e7e68d2015-05-22 12:02:25 +05302869 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04002870 fieldVariable->setQualifier(typeQualifier.qualifier);
2871
Arun Patole7e7e68d2015-05-22 12:02:25 +05302872 if (!symbolTable.declare(fieldVariable))
2873 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002874 error(field->line(), "redefinition", field->name().c_str(),
2875 "interface block member name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002876 }
2877 }
2878 }
2879 else
2880 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002881 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03002882
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002883 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05302884 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002885 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04002886
Arun Patole7e7e68d2015-05-22 12:02:25 +05302887 if (!symbolTable.declare(instanceTypeDef))
2888 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002889 error(instanceLine, "redefinition", instanceName->c_str(),
2890 "interface block instance name");
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002891 }
2892
Jamie Madillb98c3a82015-07-23 14:26:04 -04002893 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002894 symbolName = instanceTypeDef->getName();
2895 }
2896
Olli Etuaho13389b62016-10-16 11:48:18 +01002897 TIntermSymbol *blockSymbol =
2898 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line);
2899 TIntermDeclaration *declaration = new TIntermDeclaration();
2900 declaration->appendDeclarator(blockSymbol);
2901 declaration->setLine(nameLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04002902
2903 exitStructDeclaration();
Olli Etuaho13389b62016-10-16 11:48:18 +01002904 return declaration;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002905}
2906
Olli Etuaho383b7912016-08-05 11:22:59 +03002907void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002908{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002909 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002910
2911 // Embedded structure definitions are not supported per GLSL ES spec.
2912 // They aren't allowed in GLSL either, but we need to detect this here
2913 // so we don't rely on the GLSL compiler to catch it.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302914 if (mStructNestingLevel > 1)
2915 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +00002916 error(line, "", "Embedded struct definitions are not allowed");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002917 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002918}
2919
2920void TParseContext::exitStructDeclaration()
2921{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002922 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002923}
2924
Olli Etuaho8a176262016-08-16 14:23:01 +03002925void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002926{
Jamie Madillacb4b812016-11-07 13:50:29 -05002927 if (!sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +05302928 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002929 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002930 }
2931
Arun Patole7e7e68d2015-05-22 12:02:25 +05302932 if (field.type()->getBasicType() != EbtStruct)
2933 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002934 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002935 }
2936
2937 // We're already inside a structure definition at this point, so add
2938 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302939 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2940 {
Jamie Madill41a49272014-03-18 16:10:13 -04002941 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002942 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
2943 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04002944 std::string reason = reasonStream.str();
2945 error(line, reason.c_str(), field.name().c_str(), "");
Olli Etuaho8a176262016-08-16 14:23:01 +03002946 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002947 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002948}
2949
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00002950//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002951// Parse an array index expression
2952//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002953TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
2954 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302955 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002956{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002957 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2958 {
2959 if (baseExpression->getAsSymbolNode())
2960 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302961 error(location, " left of '[' is not of type array, matrix, or vector ",
2962 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002963 }
2964 else
2965 {
2966 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2967 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002968
2969 TConstantUnion *unionArray = new TConstantUnion[1];
2970 unionArray->setFConst(0.0f);
2971 return intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst),
2972 location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002973 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002974
Jamie Madill21c1e452014-12-29 11:33:41 -05002975 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2976
Olli Etuaho36b05142015-11-12 13:10:42 +02002977 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
2978 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
2979 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
2980 // index is a constant expression.
2981 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
2982 {
2983 if (baseExpression->isInterfaceBlock())
2984 {
2985 error(
2986 location, "", "[",
2987 "array indexes for interface blocks arrays must be constant integral expressions");
Olli Etuaho36b05142015-11-12 13:10:42 +02002988 }
2989 else if (baseExpression->getQualifier() == EvqFragmentOut)
2990 {
2991 error(location, "", "[",
2992 "array indexes for fragment outputs must be constant integral expressions");
Olli Etuaho36b05142015-11-12 13:10:42 +02002993 }
Olli Etuaho3e960462015-11-12 15:58:39 +02002994 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
2995 {
2996 error(location, "", "[", "array index for gl_FragData must be constant zero");
Olli Etuaho3e960462015-11-12 15:58:39 +02002997 }
Olli Etuaho36b05142015-11-12 13:10:42 +02002998 }
2999
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003000 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04003001 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003002 // If an out-of-range index is not qualified as constant, the behavior in the spec is
3003 // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
3004 // constant fold expressions that are not constant expressions). The most compatible way to
3005 // handle this case is to report a warning instead of an error and force the index to be in
3006 // the correct range.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003007 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003008 int index = indexConstantUnion->getIConst(0);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003009
3010 int safeIndex = -1;
3011
3012 if (baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04003013 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003014 if (baseExpression->getQualifier() == EvqFragData && index > 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003015 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003016 if (mShaderSpec == SH_WEBGL2_SPEC)
3017 {
3018 // Error has been already generated if index is not const.
3019 if (indexExpression->getQualifier() == EvqConst)
3020 {
3021 error(location, "", "[",
3022 "array index for gl_FragData must be constant zero");
3023 }
3024 safeIndex = 0;
3025 }
3026 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
3027 {
3028 outOfRangeError(outOfRangeIndexIsError, location, "", "[",
3029 "array index for gl_FragData must be zero when "
3030 "GL_EXT_draw_buffers is disabled");
3031 safeIndex = 0;
3032 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03003033 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003034 // Only do generic out-of-range check if similar error hasn't already been reported.
3035 if (safeIndex < 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003036 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003037 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3038 baseExpression->getArraySize(),
3039 "array index out of range", "[]");
3040 }
3041 }
3042 else if (baseExpression->isMatrix())
3043 {
3044 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
Olli Etuaho90892fb2016-07-14 14:44:51 +03003045 baseExpression->getType().getCols(),
3046 "matrix field selection out of range", "[]");
Jamie Madill7164cf42013-07-08 13:30:59 -04003047 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003048 else if (baseExpression->isVector())
Jamie Madill7164cf42013-07-08 13:30:59 -04003049 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003050 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3051 baseExpression->getType().getNominalSize(),
3052 "vector field selection out of range", "[]");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003053 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003054
3055 ASSERT(safeIndex >= 0);
3056 // Data of constant unions can't be changed, because it may be shared with other
3057 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
3058 // sanitized object.
3059 if (safeIndex != index)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003060 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003061 TConstantUnion *safeConstantUnion = new TConstantUnion();
3062 safeConstantUnion->setIConst(safeIndex);
3063 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003064 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003065
3066 return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location,
3067 &mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003068 }
Jamie Madill7164cf42013-07-08 13:30:59 -04003069 else
3070 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003071 return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location,
3072 &mDiagnostics);
Jamie Madill7164cf42013-07-08 13:30:59 -04003073 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003074}
3075
Olli Etuaho90892fb2016-07-14 14:44:51 +03003076int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
3077 const TSourceLoc &location,
3078 int index,
3079 int arraySize,
3080 const char *reason,
3081 const char *token)
3082{
3083 if (index >= arraySize || index < 0)
3084 {
3085 std::stringstream extraInfoStream;
3086 extraInfoStream << "'" << index << "'";
3087 std::string extraInfo = extraInfoStream.str();
3088 outOfRangeError(outOfRangeIndexIsError, location, reason, token, extraInfo.c_str());
3089 if (index < 0)
3090 {
3091 return 0;
3092 }
3093 else
3094 {
3095 return arraySize - 1;
3096 }
3097 }
3098 return index;
3099}
3100
Jamie Madillb98c3a82015-07-23 14:26:04 -04003101TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
3102 const TSourceLoc &dotLocation,
3103 const TString &fieldString,
3104 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003105{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003106 if (baseExpression->isArray())
3107 {
3108 error(fieldLocation, "cannot apply dot operator to an array", ".");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003109 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003110 }
3111
3112 if (baseExpression->isVector())
3113 {
3114 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003115 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
3116 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003117 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003118 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003119 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003120 }
3121
Olli Etuahob6fa0432016-09-28 16:28:05 +01003122 return TIntermediate::AddSwizzle(baseExpression, fields, dotLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003123 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003124 else if (baseExpression->getBasicType() == EbtStruct)
3125 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303126 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003127 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003128 {
3129 error(dotLocation, "structure has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003130 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003131 }
3132 else
3133 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003134 bool fieldFound = false;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003135 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003136 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003137 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003138 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003139 {
3140 fieldFound = true;
3141 break;
3142 }
3143 }
3144 if (fieldFound)
3145 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003146 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3147 index->setLine(fieldLocation);
3148 return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index,
3149 dotLocation, &mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003150 }
3151 else
3152 {
3153 error(dotLocation, " no such field in structure", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003154 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003155 }
3156 }
3157 }
Jamie Madill98493dd2013-07-08 14:39:03 -04003158 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003159 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303160 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003161 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003162 {
3163 error(dotLocation, "interface block has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003164 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003165 }
3166 else
3167 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003168 bool fieldFound = false;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003169 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003170 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003171 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003172 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003173 {
3174 fieldFound = true;
3175 break;
3176 }
3177 }
3178 if (fieldFound)
3179 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003180 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3181 index->setLine(fieldLocation);
3182 return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
3183 dotLocation, &mDiagnostics);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003184 }
3185 else
3186 {
3187 error(dotLocation, " no such field in interface block", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003188 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003189 }
3190 }
3191 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003192 else
3193 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003194 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003195 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03003196 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303197 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003198 }
3199 else
3200 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303201 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03003202 " field selection requires structure, vector, or interface block on left hand "
3203 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303204 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003205 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003206 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003207 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003208}
3209
Jamie Madillb98c3a82015-07-23 14:26:04 -04003210TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3211 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003212{
Martin Radev802abe02016-08-04 17:48:32 +03003213 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003214
3215 if (qualifierType == "shared")
3216 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003217 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003218 {
3219 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
3220 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003221 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003222 }
3223 else if (qualifierType == "packed")
3224 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003225 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003226 {
3227 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
3228 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003229 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003230 }
3231 else if (qualifierType == "std140")
3232 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003233 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003234 }
3235 else if (qualifierType == "row_major")
3236 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003237 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003238 }
3239 else if (qualifierType == "column_major")
3240 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003241 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003242 }
3243 else if (qualifierType == "location")
3244 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003245 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(),
3246 "location requires an argument");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003247 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003248 else if (qualifierType == "rgba32f")
3249 {
3250 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3251 qualifier.imageInternalFormat = EiifRGBA32F;
3252 }
3253 else if (qualifierType == "rgba16f")
3254 {
3255 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3256 qualifier.imageInternalFormat = EiifRGBA16F;
3257 }
3258 else if (qualifierType == "r32f")
3259 {
3260 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3261 qualifier.imageInternalFormat = EiifR32F;
3262 }
3263 else if (qualifierType == "rgba8")
3264 {
3265 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3266 qualifier.imageInternalFormat = EiifRGBA8;
3267 }
3268 else if (qualifierType == "rgba8_snorm")
3269 {
3270 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3271 qualifier.imageInternalFormat = EiifRGBA8_SNORM;
3272 }
3273 else if (qualifierType == "rgba32i")
3274 {
3275 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3276 qualifier.imageInternalFormat = EiifRGBA32I;
3277 }
3278 else if (qualifierType == "rgba16i")
3279 {
3280 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3281 qualifier.imageInternalFormat = EiifRGBA16I;
3282 }
3283 else if (qualifierType == "rgba8i")
3284 {
3285 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3286 qualifier.imageInternalFormat = EiifRGBA8I;
3287 }
3288 else if (qualifierType == "r32i")
3289 {
3290 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3291 qualifier.imageInternalFormat = EiifR32I;
3292 }
3293 else if (qualifierType == "rgba32ui")
3294 {
3295 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3296 qualifier.imageInternalFormat = EiifRGBA32UI;
3297 }
3298 else if (qualifierType == "rgba16ui")
3299 {
3300 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3301 qualifier.imageInternalFormat = EiifRGBA16UI;
3302 }
3303 else if (qualifierType == "rgba8ui")
3304 {
3305 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3306 qualifier.imageInternalFormat = EiifRGBA8UI;
3307 }
3308 else if (qualifierType == "r32ui")
3309 {
3310 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3311 qualifier.imageInternalFormat = EiifR32UI;
3312 }
3313
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003314 else
3315 {
3316 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003317 }
3318
Jamie Madilla5efff92013-06-06 11:56:47 -04003319 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003320}
3321
Martin Radev802abe02016-08-04 17:48:32 +03003322void TParseContext::parseLocalSize(const TString &qualifierType,
3323 const TSourceLoc &qualifierTypeLine,
3324 int intValue,
3325 const TSourceLoc &intValueLine,
3326 const std::string &intValueString,
3327 size_t index,
Martin Radev4c4c8e72016-08-04 12:25:34 +03003328 sh::WorkGroupSize *localSize)
Martin Radev802abe02016-08-04 17:48:32 +03003329{
Olli Etuaho856c4972016-08-08 11:38:39 +03003330 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03003331 if (intValue < 1)
3332 {
Martin Radev4c4c8e72016-08-04 12:25:34 +03003333 std::string errorMessage = std::string(getWorkGroupSizeString(index)) + " must be positive";
Martin Radev802abe02016-08-04 17:48:32 +03003334 error(intValueLine, "out of range:", intValueString.c_str(), errorMessage.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003335 }
3336 (*localSize)[index] = intValue;
3337}
3338
Jamie Madillb98c3a82015-07-23 14:26:04 -04003339TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3340 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003341 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303342 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003343{
Martin Radev802abe02016-08-04 17:48:32 +03003344 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003345
Martin Radev802abe02016-08-04 17:48:32 +03003346 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003347
Martin Radev802abe02016-08-04 17:48:32 +03003348 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003349 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003350 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003351 if (intValue < 0)
3352 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003353 error(intValueLine, "out of range:", intValueString.c_str(),
3354 "location must be non-negative");
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003355 }
3356 else
3357 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003358 qualifier.location = intValue;
Olli Etuaho87d410c2016-09-05 13:33:26 +03003359 qualifier.locationsSpecified = 1;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003360 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003361 }
Martin Radev802abe02016-08-04 17:48:32 +03003362 else if (qualifierType == "local_size_x")
3363 {
3364 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3365 &qualifier.localSize);
3366 }
3367 else if (qualifierType == "local_size_y")
3368 {
3369 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3370 &qualifier.localSize);
3371 }
3372 else if (qualifierType == "local_size_z")
3373 {
3374 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3375 &qualifier.localSize);
3376 }
3377 else
3378 {
3379 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003380 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003381
Jamie Madilla5efff92013-06-06 11:56:47 -04003382 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003383}
3384
Olli Etuaho613b9592016-09-05 12:05:53 +03003385TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
3386{
3387 return new TTypeQualifierBuilder(
3388 new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
3389 mShaderVersion);
3390}
3391
Jamie Madillb98c3a82015-07-23 14:26:04 -04003392TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003393 TLayoutQualifier rightQualifier,
3394 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003395{
Martin Radevc28888b2016-07-22 15:27:42 +03003396 return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
3397 &mDiagnostics);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003398}
3399
Martin Radev70866b82016-07-22 15:27:42 +03003400TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
3401 const TTypeQualifierBuilder &typeQualifierBuilder,
3402 TPublicType *typeSpecifier,
3403 TFieldList *fieldList)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003404{
Olli Etuaho613b9592016-09-05 12:05:53 +03003405 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003406
Martin Radev70866b82016-07-22 15:27:42 +03003407 typeSpecifier->qualifier = typeQualifier.qualifier;
3408 typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03003409 typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03003410 typeSpecifier->invariant = typeQualifier.invariant;
3411 if (typeQualifier.precision != EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +05303412 {
Martin Radev70866b82016-07-22 15:27:42 +03003413 typeSpecifier->precision = typeQualifier.precision;
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003414 }
Martin Radev70866b82016-07-22 15:27:42 +03003415 return addStructDeclaratorList(*typeSpecifier, fieldList);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003416}
3417
Jamie Madillb98c3a82015-07-23 14:26:04 -04003418TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3419 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003420{
Martin Radev4a9cd802016-09-01 16:51:51 +03003421 checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
3422 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03003423
Martin Radev4a9cd802016-09-01 16:51:51 +03003424 checkIsNonVoid(typeSpecifier.getLine(), (*fieldList)[0]->name(), typeSpecifier.getBasicType());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003425
Martin Radev4a9cd802016-09-01 16:51:51 +03003426 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003427
Arun Patole7e7e68d2015-05-22 12:02:25 +05303428 for (unsigned int i = 0; i < fieldList->size(); ++i)
3429 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003430 //
3431 // Careful not to replace already known aspects of type, like array-ness
3432 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303433 TType *type = (*fieldList)[i]->type();
Martin Radev4a9cd802016-09-01 16:51:51 +03003434 type->setBasicType(typeSpecifier.getBasicType());
3435 type->setPrimarySize(typeSpecifier.getPrimarySize());
3436 type->setSecondarySize(typeSpecifier.getSecondarySize());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003437 type->setPrecision(typeSpecifier.precision);
3438 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003439 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
Martin Radev2cc85b32016-08-05 16:22:53 +03003440 type->setMemoryQualifier(typeSpecifier.memoryQualifier);
Martin Radev70866b82016-07-22 15:27:42 +03003441 type->setInvariant(typeSpecifier.invariant);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003442
3443 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303444 if (type->isArray())
3445 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003446 checkIsValidTypeForArray(typeSpecifier.getLine(), typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003447 }
3448 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003449 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Martin Radev4a9cd802016-09-01 16:51:51 +03003450 if (typeSpecifier.getUserDef())
Arun Patole7e7e68d2015-05-22 12:02:25 +05303451 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003452 type->setStruct(typeSpecifier.getUserDef()->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003453 }
3454
Martin Radev4a9cd802016-09-01 16:51:51 +03003455 checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003456 }
3457
Jamie Madill98493dd2013-07-08 14:39:03 -04003458 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003459}
3460
Martin Radev4a9cd802016-09-01 16:51:51 +03003461TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
3462 const TSourceLoc &nameLine,
3463 const TString *structName,
3464 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003465{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303466 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003467 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003468
Jamie Madill9b820842015-02-12 10:40:10 -05003469 // Store a bool in the struct if we're at global scope, to allow us to
3470 // skip the local struct scoping workaround in HLSL.
Jamie Madill9b820842015-02-12 10:40:10 -05003471 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003472
Jamie Madill98493dd2013-07-08 14:39:03 -04003473 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003474 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003475 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303476 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3477 if (!symbolTable.declare(userTypeDef))
3478 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003479 error(nameLine, "redefinition", structName->c_str(), "struct");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003480 }
3481 }
3482
3483 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003484 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003485 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003486 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003487 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003488 switch (qualifier)
3489 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003490 case EvqGlobal:
3491 case EvqTemporary:
3492 break;
3493 default:
3494 error(field.line(), "invalid qualifier on struct member",
3495 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003496 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003497 }
Martin Radev70866b82016-07-22 15:27:42 +03003498 if (field.type()->isInvariant())
3499 {
3500 error(field.line(), "invalid qualifier on struct member", "invariant");
3501 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003502 if (IsImage(field.type()->getBasicType()))
3503 {
3504 error(field.line(), "disallowed type in struct", field.type()->getBasicString());
3505 }
3506
3507 checkIsMemoryQualifierNotSpecified(field.type()->getMemoryQualifier(), field.line());
Martin Radev70866b82016-07-22 15:27:42 +03003508
3509 checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003510 }
3511
Martin Radev4a9cd802016-09-01 16:51:51 +03003512 TTypeSpecifierNonArray typeSpecifierNonArray;
3513 typeSpecifierNonArray.initialize(EbtStruct, structLine);
3514 typeSpecifierNonArray.userDef = structureType;
3515 typeSpecifierNonArray.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003516 exitStructDeclaration();
3517
Martin Radev4a9cd802016-09-01 16:51:51 +03003518 return typeSpecifierNonArray;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003519}
3520
Jamie Madillb98c3a82015-07-23 14:26:04 -04003521TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01003522 TIntermBlock *statementList,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003523 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003524{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003525 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003526 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003527 init->isVector())
3528 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003529 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3530 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003531 return nullptr;
3532 }
3533
Olli Etuahoac5274d2015-02-20 10:19:08 +02003534 if (statementList)
3535 {
3536 if (!ValidateSwitch::validate(switchType, this, statementList, loc))
3537 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003538 return nullptr;
3539 }
3540 }
3541
Olli Etuahoa3a36662015-02-17 13:46:51 +02003542 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3543 if (node == nullptr)
3544 {
3545 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003546 return nullptr;
3547 }
3548 return node;
3549}
3550
3551TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3552{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003553 if (mSwitchNestingLevel == 0)
3554 {
3555 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003556 return nullptr;
3557 }
3558 if (condition == nullptr)
3559 {
3560 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003561 return nullptr;
3562 }
3563 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003564 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003565 {
3566 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003567 }
3568 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003569 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3570 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3571 // fold in case labels.
3572 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003573 {
3574 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003575 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003576 TIntermCase *node = intermediate.addCase(condition, loc);
3577 if (node == nullptr)
3578 {
3579 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003580 return nullptr;
3581 }
3582 return node;
3583}
3584
3585TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3586{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003587 if (mSwitchNestingLevel == 0)
3588 {
3589 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003590 return nullptr;
3591 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003592 TIntermCase *node = intermediate.addCase(nullptr, loc);
3593 if (node == nullptr)
3594 {
3595 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003596 return nullptr;
3597 }
3598 return node;
3599}
3600
Jamie Madillb98c3a82015-07-23 14:26:04 -04003601TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3602 TIntermTyped *child,
3603 const TSourceLoc &loc,
3604 const TType *funcReturnType)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003605{
3606 if (child == nullptr)
3607 {
3608 return nullptr;
3609 }
3610
3611 switch (op)
3612 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003613 case EOpLogicalNot:
3614 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3615 child->isVector())
3616 {
3617 return nullptr;
3618 }
3619 break;
3620 case EOpBitwiseNot:
3621 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3622 child->isMatrix() || child->isArray())
3623 {
3624 return nullptr;
3625 }
3626 break;
3627 case EOpPostIncrement:
3628 case EOpPreIncrement:
3629 case EOpPostDecrement:
3630 case EOpPreDecrement:
3631 case EOpNegative:
3632 case EOpPositive:
3633 if (child->getBasicType() == EbtStruct || child->getBasicType() == EbtBool ||
Martin Radev2cc85b32016-08-05 16:22:53 +03003634 child->isArray() || IsOpaqueType(child->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -04003635 {
3636 return nullptr;
3637 }
3638 // Operators for built-ins are already type checked against their prototype.
3639 default:
3640 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003641 }
3642
Olli Etuahof119a262016-08-19 15:54:22 +03003643 TIntermUnary *node = new TIntermUnary(op, child);
3644 node->setLine(loc);
Olli Etuahof119a262016-08-19 15:54:22 +03003645
3646 TIntermTyped *foldedNode = node->fold(&mDiagnostics);
3647 if (foldedNode)
3648 return foldedNode;
3649
3650 return node;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003651}
3652
Olli Etuaho09b22472015-02-11 11:47:26 +02003653TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3654{
Olli Etuahof6c694b2015-03-26 14:50:53 +02003655 TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003656 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003657 {
3658 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003659 return child;
3660 }
3661 return node;
3662}
3663
Jamie Madillb98c3a82015-07-23 14:26:04 -04003664TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3665 TIntermTyped *child,
3666 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003667{
Olli Etuaho856c4972016-08-08 11:38:39 +03003668 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003669 return addUnaryMath(op, child, loc);
3670}
3671
Jamie Madillb98c3a82015-07-23 14:26:04 -04003672bool TParseContext::binaryOpCommonCheck(TOperator op,
3673 TIntermTyped *left,
3674 TIntermTyped *right,
3675 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003676{
Olli Etuaho244be012016-08-18 15:26:02 +03003677 if (left->getType().getStruct() || right->getType().getStruct())
3678 {
3679 switch (op)
3680 {
3681 case EOpIndexDirectStruct:
3682 ASSERT(left->getType().getStruct());
3683 break;
3684 case EOpEqual:
3685 case EOpNotEqual:
3686 case EOpAssign:
3687 case EOpInitialize:
3688 if (left->getType() != right->getType())
3689 {
3690 return false;
3691 }
3692 break;
3693 default:
3694 error(loc, "Invalid operation for structs", GetOperatorString(op));
3695 return false;
3696 }
3697 }
3698
Olli Etuahod6b14282015-03-17 14:31:35 +02003699 if (left->isArray() || right->isArray())
3700 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003701 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003702 {
3703 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3704 return false;
3705 }
3706
3707 if (left->isArray() != right->isArray())
3708 {
3709 error(loc, "array / non-array mismatch", GetOperatorString(op));
3710 return false;
3711 }
3712
3713 switch (op)
3714 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003715 case EOpEqual:
3716 case EOpNotEqual:
3717 case EOpAssign:
3718 case EOpInitialize:
3719 break;
3720 default:
3721 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3722 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02003723 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03003724 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02003725 if (left->getArraySize() != right->getArraySize())
3726 {
3727 error(loc, "array size mismatch", GetOperatorString(op));
3728 return false;
3729 }
Olli Etuahod6b14282015-03-17 14:31:35 +02003730 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003731
3732 // Check ops which require integer / ivec parameters
3733 bool isBitShift = false;
3734 switch (op)
3735 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003736 case EOpBitShiftLeft:
3737 case EOpBitShiftRight:
3738 case EOpBitShiftLeftAssign:
3739 case EOpBitShiftRightAssign:
3740 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3741 // check that the basic type is an integer type.
3742 isBitShift = true;
3743 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3744 {
3745 return false;
3746 }
3747 break;
3748 case EOpBitwiseAnd:
3749 case EOpBitwiseXor:
3750 case EOpBitwiseOr:
3751 case EOpBitwiseAndAssign:
3752 case EOpBitwiseXorAssign:
3753 case EOpBitwiseOrAssign:
3754 // It is enough to check the type of only one operand, since later it
3755 // is checked that the operand types match.
3756 if (!IsInteger(left->getBasicType()))
3757 {
3758 return false;
3759 }
3760 break;
3761 default:
3762 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003763 }
3764
3765 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3766 // So the basic type should usually match.
3767 if (!isBitShift && left->getBasicType() != right->getBasicType())
3768 {
3769 return false;
3770 }
3771
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003772 // Check that:
3773 // 1. Type sizes match exactly on ops that require that.
3774 // 2. Restrictions for structs that contain arrays or samplers are respected.
3775 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
Jamie Madillb98c3a82015-07-23 14:26:04 -04003776 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003777 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003778 case EOpAssign:
3779 case EOpInitialize:
3780 case EOpEqual:
3781 case EOpNotEqual:
3782 // ESSL 1.00 sections 5.7, 5.8, 5.9
3783 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
3784 {
3785 error(loc, "undefined operation for structs containing arrays",
3786 GetOperatorString(op));
3787 return false;
3788 }
3789 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3790 // we interpret the spec so that this extends to structs containing samplers,
3791 // similarly to ESSL 1.00 spec.
3792 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
3793 left->getType().isStructureContainingSamplers())
3794 {
3795 error(loc, "undefined operation for structs containing samplers",
3796 GetOperatorString(op));
3797 return false;
3798 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003799
3800 if ((op == EOpAssign || op == EOpInitialize) &&
3801 left->getType().isStructureContainingImages())
3802 {
3803 error(loc, "undefined operation for structs containing images",
3804 GetOperatorString(op));
3805 return false;
3806 }
Jamie Madillb98c3a82015-07-23 14:26:04 -04003807 case EOpLessThan:
3808 case EOpGreaterThan:
3809 case EOpLessThanEqual:
3810 case EOpGreaterThanEqual:
3811 if ((left->getNominalSize() != right->getNominalSize()) ||
3812 (left->getSecondarySize() != right->getSecondarySize()))
3813 {
3814 return false;
3815 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003816 break;
3817 case EOpAdd:
3818 case EOpSub:
3819 case EOpDiv:
3820 case EOpIMod:
3821 case EOpBitShiftLeft:
3822 case EOpBitShiftRight:
3823 case EOpBitwiseAnd:
3824 case EOpBitwiseXor:
3825 case EOpBitwiseOr:
3826 case EOpAddAssign:
3827 case EOpSubAssign:
3828 case EOpDivAssign:
3829 case EOpIModAssign:
3830 case EOpBitShiftLeftAssign:
3831 case EOpBitShiftRightAssign:
3832 case EOpBitwiseAndAssign:
3833 case EOpBitwiseXorAssign:
3834 case EOpBitwiseOrAssign:
3835 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
3836 {
3837 return false;
3838 }
3839
3840 // Are the sizes compatible?
3841 if (left->getNominalSize() != right->getNominalSize() ||
3842 left->getSecondarySize() != right->getSecondarySize())
3843 {
3844 // If the nominal sizes of operands do not match:
3845 // One of them must be a scalar.
3846 if (!left->isScalar() && !right->isScalar())
3847 return false;
3848
3849 // In the case of compound assignment other than multiply-assign,
3850 // the right side needs to be a scalar. Otherwise a vector/matrix
3851 // would be assigned to a scalar. A scalar can't be shifted by a
3852 // vector either.
3853 if (!right->isScalar() &&
3854 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
3855 return false;
3856 }
3857 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003858 default:
3859 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003860 }
3861
Olli Etuahod6b14282015-03-17 14:31:35 +02003862 return true;
3863}
3864
Olli Etuaho1dded802016-08-18 18:13:13 +03003865bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
3866 const TType &left,
3867 const TType &right)
3868{
3869 switch (op)
3870 {
3871 case EOpMul:
3872 case EOpMulAssign:
3873 return left.getNominalSize() == right.getNominalSize() &&
3874 left.getSecondarySize() == right.getSecondarySize();
3875 case EOpVectorTimesScalar:
3876 return true;
3877 case EOpVectorTimesScalarAssign:
3878 ASSERT(!left.isMatrix() && !right.isMatrix());
3879 return left.isVector() && !right.isVector();
3880 case EOpVectorTimesMatrix:
3881 return left.getNominalSize() == right.getRows();
3882 case EOpVectorTimesMatrixAssign:
3883 ASSERT(!left.isMatrix() && right.isMatrix());
3884 return left.isVector() && left.getNominalSize() == right.getRows() &&
3885 left.getNominalSize() == right.getCols();
3886 case EOpMatrixTimesVector:
3887 return left.getCols() == right.getNominalSize();
3888 case EOpMatrixTimesScalar:
3889 return true;
3890 case EOpMatrixTimesScalarAssign:
3891 ASSERT(left.isMatrix() && !right.isMatrix());
3892 return !right.isVector();
3893 case EOpMatrixTimesMatrix:
3894 return left.getCols() == right.getRows();
3895 case EOpMatrixTimesMatrixAssign:
3896 ASSERT(left.isMatrix() && right.isMatrix());
3897 // We need to check two things:
3898 // 1. The matrix multiplication step is valid.
3899 // 2. The result will have the same number of columns as the lvalue.
3900 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
3901
3902 default:
3903 UNREACHABLE();
3904 return false;
3905 }
3906}
3907
Jamie Madillb98c3a82015-07-23 14:26:04 -04003908TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
3909 TIntermTyped *left,
3910 TIntermTyped *right,
3911 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02003912{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003913 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003914 return nullptr;
3915
Olli Etuahofc1806e2015-03-17 13:03:11 +02003916 switch (op)
3917 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003918 case EOpEqual:
3919 case EOpNotEqual:
3920 break;
3921 case EOpLessThan:
3922 case EOpGreaterThan:
3923 case EOpLessThanEqual:
3924 case EOpGreaterThanEqual:
Olli Etuaho244be012016-08-18 15:26:02 +03003925 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3926 !right->getType().getStruct());
3927 if (left->isMatrix() || left->isVector())
Jamie Madillb98c3a82015-07-23 14:26:04 -04003928 {
3929 return nullptr;
3930 }
3931 break;
3932 case EOpLogicalOr:
3933 case EOpLogicalXor:
3934 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03003935 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3936 !right->getType().getStruct());
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00003937 if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04003938 {
3939 return nullptr;
3940 }
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00003941 // Basic types matching should have been already checked.
3942 ASSERT(right->getBasicType() == EbtBool);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003943 break;
3944 case EOpAdd:
3945 case EOpSub:
3946 case EOpDiv:
3947 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03003948 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3949 !right->getType().getStruct());
3950 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04003951 {
3952 return nullptr;
3953 }
3954 break;
3955 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03003956 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3957 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003958 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03003959 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04003960 {
3961 return nullptr;
3962 }
3963 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003964 default:
3965 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02003966 }
3967
Olli Etuaho1dded802016-08-18 18:13:13 +03003968 if (op == EOpMul)
3969 {
3970 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
3971 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
3972 {
3973 return nullptr;
3974 }
3975 }
3976
Olli Etuaho3fdec912016-08-18 15:08:06 +03003977 TIntermBinary *node = new TIntermBinary(op, left, right);
3978 node->setLine(loc);
3979
Olli Etuaho3fdec912016-08-18 15:08:06 +03003980 // See if we can fold constants.
3981 TIntermTyped *foldedNode = node->fold(&mDiagnostics);
3982 if (foldedNode)
3983 return foldedNode;
3984
3985 return node;
Olli Etuahofc1806e2015-03-17 13:03:11 +02003986}
3987
Jamie Madillb98c3a82015-07-23 14:26:04 -04003988TIntermTyped *TParseContext::addBinaryMath(TOperator op,
3989 TIntermTyped *left,
3990 TIntermTyped *right,
3991 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003992{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003993 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003994 if (node == 0)
3995 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003996 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
3997 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02003998 return left;
3999 }
4000 return node;
4001}
4002
Jamie Madillb98c3a82015-07-23 14:26:04 -04004003TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
4004 TIntermTyped *left,
4005 TIntermTyped *right,
4006 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004007{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004008 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004009 if (node == 0)
4010 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004011 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4012 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04004013 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02004014 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004015 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
4016 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004017 }
4018 return node;
4019}
4020
Olli Etuaho13389b62016-10-16 11:48:18 +01004021TIntermBinary *TParseContext::createAssign(TOperator op,
4022 TIntermTyped *left,
4023 TIntermTyped *right,
4024 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004025{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004026 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004027 {
Olli Etuaho1dded802016-08-18 18:13:13 +03004028 if (op == EOpMulAssign)
4029 {
4030 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
4031 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4032 {
4033 return nullptr;
4034 }
4035 }
Olli Etuaho3fdec912016-08-18 15:08:06 +03004036 TIntermBinary *node = new TIntermBinary(op, left, right);
4037 node->setLine(loc);
4038
Olli Etuaho3fdec912016-08-18 15:08:06 +03004039 return node;
Olli Etuahod6b14282015-03-17 14:31:35 +02004040 }
4041 return nullptr;
4042}
4043
Jamie Madillb98c3a82015-07-23 14:26:04 -04004044TIntermTyped *TParseContext::addAssign(TOperator op,
4045 TIntermTyped *left,
4046 TIntermTyped *right,
4047 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004048{
4049 TIntermTyped *node = createAssign(op, left, right, loc);
4050 if (node == nullptr)
4051 {
4052 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02004053 return left;
4054 }
4055 return node;
4056}
4057
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004058TIntermTyped *TParseContext::addComma(TIntermTyped *left,
4059 TIntermTyped *right,
4060 const TSourceLoc &loc)
4061{
Corentin Wallez0d959252016-07-12 17:26:32 -04004062 // WebGL2 section 5.26, the following results in an error:
4063 // "Sequence operator applied to void, arrays, or structs containing arrays"
Jamie Madilld7b1ab52016-12-12 14:42:19 -05004064 if (mShaderSpec == SH_WEBGL2_SPEC &&
4065 (left->isArray() || left->getBasicType() == EbtVoid ||
4066 left->getType().isStructureContainingArrays() || right->isArray() ||
4067 right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
Corentin Wallez0d959252016-07-12 17:26:32 -04004068 {
4069 error(loc,
4070 "sequence operator is not allowed for void, arrays, or structs containing arrays",
4071 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04004072 }
4073
Olli Etuaho4db7ded2016-10-13 12:23:11 +01004074 return TIntermediate::AddComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004075}
4076
Olli Etuaho49300862015-02-20 14:54:49 +02004077TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
4078{
4079 switch (op)
4080 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004081 case EOpContinue:
4082 if (mLoopNestingLevel <= 0)
4083 {
4084 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004085 }
4086 break;
4087 case EOpBreak:
4088 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
4089 {
4090 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004091 }
4092 break;
4093 case EOpReturn:
4094 if (mCurrentFunctionType->getBasicType() != EbtVoid)
4095 {
4096 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004097 }
4098 break;
4099 default:
4100 // No checks for discard
4101 break;
Olli Etuaho49300862015-02-20 14:54:49 +02004102 }
4103 return intermediate.addBranch(op, loc);
4104}
4105
Jamie Madillb98c3a82015-07-23 14:26:04 -04004106TIntermBranch *TParseContext::addBranch(TOperator op,
4107 TIntermTyped *returnValue,
4108 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02004109{
4110 ASSERT(op == EOpReturn);
4111 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004112 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02004113 {
4114 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004115 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004116 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02004117 {
4118 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004119 }
4120 return intermediate.addBranch(op, returnValue, loc);
4121}
4122
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004123void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
4124{
4125 ASSERT(!functionCall->isUserDefined());
Olli Etuahobd674552016-10-06 13:28:42 +01004126 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004127 TIntermNode *offset = nullptr;
4128 TIntermSequence *arguments = functionCall->getSequence();
4129 if (name.compare(0, 16, "texelFetchOffset") == 0 ||
4130 name.compare(0, 16, "textureLodOffset") == 0 ||
4131 name.compare(0, 20, "textureProjLodOffset") == 0 ||
4132 name.compare(0, 17, "textureGradOffset") == 0 ||
4133 name.compare(0, 21, "textureProjGradOffset") == 0)
4134 {
4135 offset = arguments->back();
4136 }
4137 else if (name.compare(0, 13, "textureOffset") == 0 ||
4138 name.compare(0, 17, "textureProjOffset") == 0)
4139 {
4140 // A bias parameter might follow the offset parameter.
4141 ASSERT(arguments->size() >= 3);
4142 offset = (*arguments)[2];
4143 }
4144 if (offset != nullptr)
4145 {
4146 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
4147 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
4148 {
4149 TString unmangledName = TFunction::unmangleName(name);
4150 error(functionCall->getLine(), "Texture offset must be a constant expression",
4151 unmangledName.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004152 }
4153 else
4154 {
4155 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
4156 size_t size = offsetConstantUnion->getType().getObjectSize();
4157 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
4158 for (size_t i = 0u; i < size; ++i)
4159 {
4160 int offsetValue = values[i].getIConst();
4161 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
4162 {
4163 std::stringstream tokenStream;
4164 tokenStream << offsetValue;
4165 std::string token = tokenStream.str();
4166 error(offset->getLine(), "Texture offset value out of valid range",
4167 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004168 }
4169 }
4170 }
4171 }
4172}
4173
Martin Radev2cc85b32016-08-05 16:22:53 +03004174// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
4175void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
4176{
4177 ASSERT(!functionCall->isUserDefined());
4178 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
4179
4180 if (name.compare(0, 5, "image") == 0)
4181 {
4182 TIntermSequence *arguments = functionCall->getSequence();
4183 TIntermNode *imageNode = (*arguments)[0];
4184 TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode();
4185
4186 const TMemoryQualifier &memoryQualifier = imageSymbol->getMemoryQualifier();
4187
4188 if (name.compare(5, 5, "Store") == 0)
4189 {
4190 if (memoryQualifier.readonly)
4191 {
4192 error(imageNode->getLine(),
4193 "'imageStore' cannot be used with images qualified as 'readonly'",
4194 imageSymbol->getSymbol().c_str());
4195 }
4196 }
4197 else if (name.compare(5, 4, "Load") == 0)
4198 {
4199 if (memoryQualifier.writeonly)
4200 {
4201 error(imageNode->getLine(),
4202 "'imageLoad' cannot be used with images qualified as 'writeonly'",
4203 imageSymbol->getSymbol().c_str());
4204 }
4205 }
4206 }
4207}
4208
4209// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
4210void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
4211 const TFunction *functionDefinition,
4212 const TIntermAggregate *functionCall)
4213{
4214 ASSERT(functionCall->isUserDefined());
4215
4216 const TIntermSequence &arguments = *functionCall->getSequence();
4217
4218 ASSERT(functionDefinition->getParamCount() == arguments.size());
4219
4220 for (size_t i = 0; i < arguments.size(); ++i)
4221 {
4222 const TType &functionArgumentType = arguments[i]->getAsTyped()->getType();
4223 const TType &functionParameterType = *functionDefinition->getParam(i).type;
4224 ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
4225
4226 if (IsImage(functionArgumentType.getBasicType()))
4227 {
4228 const TMemoryQualifier &functionArgumentMemoryQualifier =
4229 functionArgumentType.getMemoryQualifier();
4230 const TMemoryQualifier &functionParameterMemoryQualifier =
4231 functionParameterType.getMemoryQualifier();
4232 if (functionArgumentMemoryQualifier.readonly &&
4233 !functionParameterMemoryQualifier.readonly)
4234 {
4235 error(functionCall->getLine(),
4236 "Function call discards the 'readonly' qualifier from image",
4237 arguments[i]->getAsSymbolNode()->getSymbol().c_str());
4238 }
4239
4240 if (functionArgumentMemoryQualifier.writeonly &&
4241 !functionParameterMemoryQualifier.writeonly)
4242 {
4243 error(functionCall->getLine(),
4244 "Function call discards the 'writeonly' qualifier from image",
4245 arguments[i]->getAsSymbolNode()->getSymbol().c_str());
4246 }
Martin Radev049edfa2016-11-11 14:35:37 +02004247
4248 if (functionArgumentMemoryQualifier.coherent &&
4249 !functionParameterMemoryQualifier.coherent)
4250 {
4251 error(functionCall->getLine(),
4252 "Function call discards the 'coherent' qualifier from image",
4253 arguments[i]->getAsSymbolNode()->getSymbol().c_str());
4254 }
4255
4256 if (functionArgumentMemoryQualifier.volatileQualifier &&
4257 !functionParameterMemoryQualifier.volatileQualifier)
4258 {
4259 error(functionCall->getLine(),
4260 "Function call discards the 'volatile' qualifier from image",
4261 arguments[i]->getAsSymbolNode()->getSymbol().c_str());
4262 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004263 }
4264 }
4265}
4266
Jamie Madillb98c3a82015-07-23 14:26:04 -04004267TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
4268 TIntermNode *paramNode,
4269 TIntermNode *thisNode,
4270 const TSourceLoc &loc,
4271 bool *fatalError)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004272{
Jamie Madillb98c3a82015-07-23 14:26:04 -04004273 *fatalError = false;
4274 TOperator op = fnCall->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004275 TIntermTyped *callNode = nullptr;
4276
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004277 if (thisNode != nullptr)
4278 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -04004279 TConstantUnion *unionArray = new TConstantUnion[1];
Jamie Madillb98c3a82015-07-23 14:26:04 -04004280 int arraySize = 0;
Jamie Madilld7b1ab52016-12-12 14:42:19 -05004281 TIntermTyped *typedThis = thisNode->getAsTyped();
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004282 if (fnCall->getName() != "length")
4283 {
4284 error(loc, "invalid method", fnCall->getName().c_str());
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004285 }
4286 else if (paramNode != nullptr)
4287 {
4288 error(loc, "method takes no parameters", "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004289 }
4290 else if (typedThis == nullptr || !typedThis->isArray())
4291 {
4292 error(loc, "length can only be called on arrays", "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004293 }
4294 else
4295 {
Olli Etuaho96e67382015-04-23 14:27:02 +03004296 arraySize = typedThis->getArraySize();
Olli Etuaho39282e12015-04-23 15:41:48 +03004297 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004298 {
Olli Etuaho39282e12015-04-23 15:41:48 +03004299 // This code path can be hit with expressions like these:
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004300 // (a = b).length()
Olli Etuaho39282e12015-04-23 15:41:48 +03004301 // (func()).length()
4302 // (int[3](0, 1, 2)).length()
Jamie Madillb98c3a82015-07-23 14:26:04 -04004303 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
4304 // expression.
4305 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
4306 // spec section 5.9 which allows "An array, vector or matrix expression with the
4307 // length method applied".
4308 error(loc, "length can only be called on array names, not on array expressions",
4309 "length");
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004310 }
4311 }
Olli Etuaho96e67382015-04-23 14:27:02 +03004312 unionArray->setIConst(arraySize);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004313 callNode =
4314 intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004315 }
4316 else if (op != EOpNull)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004317 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004318 // Then this should be a constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +03004319 callNode = addConstructor(paramNode, op, fnCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004320 }
4321 else
4322 {
4323 //
4324 // Not a constructor. Find it in the symbol table.
4325 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05304326 const TFunction *fnCandidate;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004327 bool builtIn;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004328 fnCandidate = findFunction(loc, fnCall, mShaderVersion, &builtIn);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004329 if (fnCandidate)
4330 {
4331 //
4332 // A declared function.
4333 //
Olli Etuaho383b7912016-08-05 11:22:59 +03004334 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004335 {
Olli Etuaho856c4972016-08-08 11:38:39 +03004336 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004337 }
4338 op = fnCandidate->getBuiltInOp();
4339 if (builtIn && op != EOpNull)
4340 {
4341 //
4342 // A function call mapped to a built-in operation.
4343 //
4344 if (fnCandidate->getParamCount() == 1)
4345 {
4346 //
4347 // Treat it like a built-in unary operator.
4348 //
Olli Etuaho15c2ac32015-11-09 15:51:43 +02004349 TIntermAggregate *paramAgg = paramNode->getAsAggregate();
4350 paramNode = paramAgg->getSequence()->front();
Jamie Madilld7b1ab52016-12-12 14:42:19 -05004351 callNode = createUnaryMath(op, paramNode->getAsTyped(), loc,
Jamie Madillb98c3a82015-07-23 14:26:04 -04004352 &fnCandidate->getReturnType());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004353 if (callNode == nullptr)
4354 {
4355 std::stringstream extraInfoStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004356 extraInfoStream
4357 << "built in unary operator function. Type: "
4358 << static_cast<TIntermTyped *>(paramNode)->getCompleteString();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004359 std::string extraInfo = extraInfoStream.str();
Jamie Madillb98c3a82015-07-23 14:26:04 -04004360 error(paramNode->getLine(), " wrong operand type", "Internal Error",
4361 extraInfo.c_str());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004362 *fatalError = true;
4363 return nullptr;
4364 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004365 }
4366 else
4367 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004368 TIntermAggregate *aggregate =
4369 intermediate.setAggregateOperator(paramNode, op, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004370 aggregate->setType(fnCandidate->getReturnType());
4371 aggregate->setPrecisionFromChildren();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02004372 if (aggregate->areChildrenConstQualified())
4373 {
4374 aggregate->getTypePointer()->setQualifier(EvqConst);
4375 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004376
4377 // Some built-in functions have out parameters too.
4378 functionCallLValueErrorCheck(fnCandidate, aggregate);
Arun Patole274f0702015-05-05 13:33:30 +05304379
Olli Etuaho7c3848e2015-11-04 13:19:17 +02004380 // See if we can constant fold a built-in. Note that this may be possible even
4381 // if it is not const-qualified.
Olli Etuahof119a262016-08-19 15:54:22 +03004382 TIntermTyped *foldedNode =
4383 intermediate.foldAggregateBuiltIn(aggregate, &mDiagnostics);
Arun Patole274f0702015-05-05 13:33:30 +05304384 if (foldedNode)
4385 {
Arun Patole274f0702015-05-05 13:33:30 +05304386 callNode = foldedNode;
4387 }
Olli Etuahob43846e2015-06-02 18:18:57 +03004388 else
4389 {
4390 callNode = aggregate;
4391 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004392 }
4393 }
4394 else
4395 {
4396 // This is a real function call
Jamie Madillb98c3a82015-07-23 14:26:04 -04004397 TIntermAggregate *aggregate =
4398 intermediate.setAggregateOperator(paramNode, EOpFunctionCall, loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004399 aggregate->setType(fnCandidate->getReturnType());
4400
Jamie Madillb98c3a82015-07-23 14:26:04 -04004401 // this is how we know whether the given function is a builtIn function or a user
4402 // defined function
4403 // if builtIn == false, it's a userDefined -> could be an overloaded
4404 // builtIn function also
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004405 // if builtIn == true, it's definitely a builtIn function with EOpNull
4406 if (!builtIn)
4407 aggregate->setUserDefined();
Olli Etuahobd674552016-10-06 13:28:42 +01004408 aggregate->getFunctionSymbolInfo()->setFromFunction(*fnCandidate);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004409
Olli Etuahobd674552016-10-06 13:28:42 +01004410 // This needs to happen after the function info including name is set
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004411 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004412 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004413 aggregate->setBuiltInFunctionPrecision();
4414
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004415 checkTextureOffsetConst(aggregate);
Martin Radev2cc85b32016-08-05 16:22:53 +03004416
4417 checkImageMemoryAccessForBuiltinFunctions(aggregate);
4418 }
4419 else
4420 {
4421 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, aggregate);
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004422 }
4423
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004424 callNode = aggregate;
4425
4426 functionCallLValueErrorCheck(fnCandidate, aggregate);
4427 }
4428 }
4429 else
4430 {
4431 // error message was put out by findFunction()
4432 // Put on a dummy node for error recovery
Jamie Madill6ba6ead2015-05-04 14:21:21 -04004433 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004434 unionArray->setFConst(0.0f);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004435 callNode = intermediate.addConstantUnion(unionArray,
4436 TType(EbtFloat, EbpUndefined, EvqConst), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004437 }
4438 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004439 return callNode;
4440}
4441
Jamie Madillb98c3a82015-07-23 14:26:04 -04004442TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004443 TIntermTyped *trueExpression,
4444 TIntermTyped *falseExpression,
Olli Etuaho52901742015-04-15 13:42:45 +03004445 const TSourceLoc &loc)
4446{
Olli Etuaho856c4972016-08-08 11:38:39 +03004447 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03004448
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004449 if (trueExpression->getType() != falseExpression->getType())
Olli Etuaho52901742015-04-15 13:42:45 +03004450 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004451 binaryOpError(loc, ":", trueExpression->getCompleteString(),
4452 falseExpression->getCompleteString());
4453 return falseExpression;
Olli Etuaho52901742015-04-15 13:42:45 +03004454 }
Olli Etuahode318b22016-10-25 16:18:25 +01004455 if (IsOpaqueType(trueExpression->getBasicType()))
4456 {
4457 // ESSL 1.00 section 4.1.7
4458 // ESSL 3.00 section 4.1.7
4459 // Opaque/sampler types are not allowed in most types of expressions, including ternary.
4460 // Note that structs containing opaque types don't need to be checked as structs are
4461 // forbidden below.
4462 error(loc, "ternary operator is not allowed for opaque types", ":");
4463 return falseExpression;
4464 }
4465
Olli Etuahoa2d53032015-04-15 14:14:44 +03004466 // ESSL1 sections 5.2 and 5.7:
4467 // ESSL3 section 5.7:
4468 // Ternary operator is not among the operators allowed for structures/arrays.
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004469 if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
Olli Etuahoa2d53032015-04-15 14:14:44 +03004470 {
4471 error(loc, "ternary operator is not allowed for structures or arrays", ":");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004472 return falseExpression;
Olli Etuahoa2d53032015-04-15 14:14:44 +03004473 }
Corentin Wallez0d959252016-07-12 17:26:32 -04004474 // WebGL2 section 5.26, the following results in an error:
4475 // "Ternary operator applied to void, arrays, or structs containing arrays"
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004476 if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
Corentin Wallez0d959252016-07-12 17:26:32 -04004477 {
4478 error(loc, "ternary operator is not allowed for void", ":");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004479 return falseExpression;
Corentin Wallez0d959252016-07-12 17:26:32 -04004480 }
4481
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004482 return TIntermediate::AddTernarySelection(cond, trueExpression, falseExpression, loc);
Olli Etuaho52901742015-04-15 13:42:45 +03004483}
Olli Etuaho49300862015-02-20 14:54:49 +02004484
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004485//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004486// Parse an array of strings using yyparse.
4487//
4488// Returns 0 for success.
4489//
Jamie Madillb98c3a82015-07-23 14:26:04 -04004490int PaParseStrings(size_t count,
4491 const char *const string[],
4492 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05304493 TParseContext *context)
4494{
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004495 if ((count == 0) || (string == NULL))
4496 return 1;
4497
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004498 if (glslang_initialize(context))
4499 return 1;
4500
alokp@chromium.org408c45e2012-04-05 15:54:43 +00004501 int error = glslang_scan(count, string, length, context);
4502 if (!error)
4503 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004504
alokp@chromium.org73bc2982012-06-19 18:48:05 +00004505 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00004506
alokp@chromium.org6b495712012-06-29 00:06:58 +00004507 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004508}
Jamie Madill45bcc782016-11-07 13:58:48 -05004509
4510} // namespace sh