blob: 73994f6faed2dd2ed2674de1c4456255e712e71d [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
jchen104cdac9e2017-05-08 11:01:20 +080012#include "common/mathutil.h"
daniel@transgaming.comb401a922012-10-26 18:58:24 +000013#include "compiler/preprocessor/SourceLocation.h"
Dmitry Skiba01971112015-07-10 14:54:00 -040014#include "compiler/translator/Cache.h"
Olli Etuahob0c645e2015-05-12 14:25:36 +030015#include "compiler/translator/ValidateGlobalInitializer.h"
jchen104cdac9e2017-05-08 11:01:20 +080016#include "compiler/translator/ValidateSwitch.h"
17#include "compiler/translator/glslang.h"
Olli Etuaho37ad4742015-04-27 13:18:50 +030018#include "compiler/translator/util.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000019
Jamie Madill45bcc782016-11-07 13:58:48 -050020namespace sh
21{
22
alokp@chromium.org8b851c62012-06-15 16:25:11 +000023///////////////////////////////////////////////////////////////////////
24//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000025// Sub- vector and matrix fields
26//
27////////////////////////////////////////////////////////////////////////
28
Martin Radev2cc85b32016-08-05 16:22:53 +030029namespace
30{
31
32const int kWebGLMaxStructNesting = 4;
33
34bool ContainsSampler(const TType &type)
35{
36 if (IsSampler(type.getBasicType()))
37 return true;
38
jchen10cc2a10e2017-05-03 14:05:12 +080039 if (type.getBasicType() == EbtStruct)
Martin Radev2cc85b32016-08-05 16:22:53 +030040 {
41 const TFieldList &fields = type.getStruct()->fields();
42 for (unsigned int i = 0; i < fields.size(); ++i)
43 {
44 if (ContainsSampler(*fields[i]->type()))
45 return true;
46 }
47 }
48
49 return false;
50}
51
Olli Etuaho485eefd2017-02-14 17:40:06 +000052// Get a token from an image argument to use as an error message token.
53const char *GetImageArgumentToken(TIntermTyped *imageNode)
54{
55 ASSERT(IsImage(imageNode->getBasicType()));
56 while (imageNode->getAsBinaryNode() &&
57 (imageNode->getAsBinaryNode()->getOp() == EOpIndexIndirect ||
58 imageNode->getAsBinaryNode()->getOp() == EOpIndexDirect))
59 {
60 imageNode = imageNode->getAsBinaryNode()->getLeft();
61 }
62 TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode();
63 if (imageSymbol)
64 {
65 return imageSymbol->getSymbol().c_str();
66 }
67 return "image";
68}
69
Martin Radev2cc85b32016-08-05 16:22:53 +030070} // namespace
71
jchen104cdac9e2017-05-08 11:01:20 +080072// This tracks each binding point's current default offset for inheritance of subsequent
73// variables using the same binding, and keeps offsets unique and non overlapping.
74// See GLSL ES 3.1, section 4.4.6.
75class TParseContext::AtomicCounterBindingState
76{
77 public:
78 AtomicCounterBindingState() : mDefaultOffset(0) {}
79 // Inserts a new span and returns -1 if overlapping, else returns the starting offset of
80 // newly inserted span.
81 int insertSpan(int start, size_t length)
82 {
83 gl::RangeI newSpan(start, start + static_cast<int>(length));
84 for (const auto &span : mSpans)
85 {
86 if (newSpan.intersects(span))
87 {
88 return -1;
89 }
90 }
91 mSpans.push_back(newSpan);
92 mDefaultOffset = newSpan.high();
93 return start;
94 }
95 // Inserts a new span starting from the default offset.
96 int appendSpan(size_t length) { return insertSpan(mDefaultOffset, length); }
97 void setDefaultOffset(int offset) { mDefaultOffset = offset; }
98
99 private:
100 int mDefaultOffset;
101 std::vector<gl::RangeI> mSpans;
102};
103
Jamie Madillacb4b812016-11-07 13:50:29 -0500104TParseContext::TParseContext(TSymbolTable &symt,
105 TExtensionBehavior &ext,
106 sh::GLenum type,
107 ShShaderSpec spec,
108 ShCompileOptions options,
109 bool checksPrecErrors,
Olli Etuaho77ba4082016-12-16 12:01:18 +0000110 TDiagnostics *diagnostics,
Jamie Madillacb4b812016-11-07 13:50:29 -0500111 const ShBuiltInResources &resources)
112 : intermediate(),
113 symbolTable(symt),
Olli Etuahobb7e5a72017-04-24 10:16:44 +0300114 mDeferredNonEmptyDeclarationErrorCheck(false),
Jamie Madillacb4b812016-11-07 13:50:29 -0500115 mShaderType(type),
116 mShaderSpec(spec),
117 mCompileOptions(options),
118 mShaderVersion(100),
119 mTreeRoot(nullptr),
120 mLoopNestingLevel(0),
121 mStructNestingLevel(0),
122 mSwitchNestingLevel(0),
123 mCurrentFunctionType(nullptr),
124 mFunctionReturnsValue(false),
125 mChecksPrecisionErrors(checksPrecErrors),
126 mFragmentPrecisionHighOnESSL1(false),
127 mDefaultMatrixPacking(EmpColumnMajor),
128 mDefaultBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
Olli Etuaho77ba4082016-12-16 12:01:18 +0000129 mDiagnostics(diagnostics),
Jamie Madillacb4b812016-11-07 13:50:29 -0500130 mDirectiveHandler(ext,
Olli Etuaho77ba4082016-12-16 12:01:18 +0000131 *mDiagnostics,
Jamie Madillacb4b812016-11-07 13:50:29 -0500132 mShaderVersion,
133 mShaderType,
134 resources.WEBGL_debug_shader_precision == 1),
Olli Etuaho77ba4082016-12-16 12:01:18 +0000135 mPreprocessor(mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()),
Jamie Madillacb4b812016-11-07 13:50:29 -0500136 mScanner(nullptr),
137 mUsesFragData(false),
138 mUsesFragColor(false),
139 mUsesSecondaryOutputs(false),
140 mMinProgramTexelOffset(resources.MinProgramTexelOffset),
141 mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
Olli Etuaho09b04a22016-12-15 13:30:26 +0000142 mMultiviewAvailable(resources.OVR_multiview == 1),
Jamie Madillacb4b812016-11-07 13:50:29 -0500143 mComputeShaderLocalSizeDeclared(false),
Olli Etuaho09b04a22016-12-15 13:30:26 +0000144 mNumViews(-1),
145 mMaxNumViews(resources.MaxViewsOVR),
Olli Etuaho43364892017-02-13 16:00:12 +0000146 mMaxImageUnits(resources.MaxImageUnits),
147 mMaxCombinedTextureImageUnits(resources.MaxCombinedTextureImageUnits),
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000148 mMaxUniformLocations(resources.MaxUniformLocations),
jchen10af713a22017-04-19 09:10:56 +0800149 mMaxUniformBufferBindings(resources.MaxUniformBufferBindings),
jchen104cdac9e2017-05-08 11:01:20 +0800150 mMaxAtomicCounterBindings(resources.MaxAtomicCounterBindings),
Jamie Madillacb4b812016-11-07 13:50:29 -0500151 mDeclaringFunction(false)
152{
153 mComputeShaderLocalSize.fill(-1);
154}
155
jchen104cdac9e2017-05-08 11:01:20 +0800156TParseContext::~TParseContext()
157{
158}
159
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000160//
161// Look at a '.' field selector string and change it into offsets
162// for a vector.
163//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400164bool TParseContext::parseVectorFields(const TString &compString,
165 int vecSize,
166 TVectorFields &fields,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530167 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000168{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400169 fields.num = (int)compString.size();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530170 if (fields.num > 4)
171 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000172 error(line, "illegal vector field selection", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000173 return false;
174 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175
Jamie Madillb98c3a82015-07-23 14:26:04 -0400176 enum
177 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000178 exyzw,
179 ergba,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000180 estpq
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000181 } fieldSet[4];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182
Arun Patole7e7e68d2015-05-22 12:02:25 +0530183 for (int i = 0; i < fields.num; ++i)
184 {
185 switch (compString[i])
186 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400187 case 'x':
188 fields.offsets[i] = 0;
189 fieldSet[i] = exyzw;
190 break;
191 case 'r':
192 fields.offsets[i] = 0;
193 fieldSet[i] = ergba;
194 break;
195 case 's':
196 fields.offsets[i] = 0;
197 fieldSet[i] = estpq;
198 break;
199 case 'y':
200 fields.offsets[i] = 1;
201 fieldSet[i] = exyzw;
202 break;
203 case 'g':
204 fields.offsets[i] = 1;
205 fieldSet[i] = ergba;
206 break;
207 case 't':
208 fields.offsets[i] = 1;
209 fieldSet[i] = estpq;
210 break;
211 case 'z':
212 fields.offsets[i] = 2;
213 fieldSet[i] = exyzw;
214 break;
215 case 'b':
216 fields.offsets[i] = 2;
217 fieldSet[i] = ergba;
218 break;
219 case 'p':
220 fields.offsets[i] = 2;
221 fieldSet[i] = estpq;
222 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530223
Jamie Madillb98c3a82015-07-23 14:26:04 -0400224 case 'w':
225 fields.offsets[i] = 3;
226 fieldSet[i] = exyzw;
227 break;
228 case 'a':
229 fields.offsets[i] = 3;
230 fieldSet[i] = ergba;
231 break;
232 case 'q':
233 fields.offsets[i] = 3;
234 fieldSet[i] = estpq;
235 break;
236 default:
237 error(line, "illegal vector field selection", compString.c_str());
238 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000239 }
240 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241
Arun Patole7e7e68d2015-05-22 12:02:25 +0530242 for (int i = 0; i < fields.num; ++i)
243 {
244 if (fields.offsets[i] >= vecSize)
245 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400246 error(line, "vector field selection out of range", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000247 return false;
248 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249
Arun Patole7e7e68d2015-05-22 12:02:25 +0530250 if (i > 0)
251 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400252 if (fieldSet[i] != fieldSet[i - 1])
Arun Patole7e7e68d2015-05-22 12:02:25 +0530253 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400254 error(line, "illegal - vector component fields not from the same set",
255 compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000256 return false;
257 }
258 }
259 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000261 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262}
263
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000264///////////////////////////////////////////////////////////////////////
265//
266// Errors
267//
268////////////////////////////////////////////////////////////////////////
269
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270//
271// Used by flex/bison to output all syntax and parsing errors.
272//
Olli Etuaho4de340a2016-12-16 09:32:03 +0000273void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000275 mDiagnostics->error(loc, reason, token);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000276}
277
Olli Etuaho4de340a2016-12-16 09:32:03 +0000278void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530279{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000280 mDiagnostics->warning(loc, reason, token);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +0000281}
282
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200283void TParseContext::outOfRangeError(bool isError,
284 const TSourceLoc &loc,
285 const char *reason,
Olli Etuaho4de340a2016-12-16 09:32:03 +0000286 const char *token)
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200287{
288 if (isError)
289 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000290 error(loc, reason, token);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200291 }
292 else
293 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000294 warning(loc, reason, token);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200295 }
296}
297
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000298//
299// Same error message for all places assignments don't work.
300//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530301void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000303 std::stringstream reasonStream;
304 reasonStream << "cannot convert from '" << right << "' to '" << left << "'";
305 std::string reason = reasonStream.str();
306 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000307}
308
309//
310// Same error message for all places unary operations don't work.
311//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530312void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000313{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000314 std::stringstream reasonStream;
315 reasonStream << "wrong operand type - no operation '" << op
316 << "' exists that takes an operand of type " << operand
317 << " (or there is no acceptable conversion)";
318 std::string reason = reasonStream.str();
319 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000320}
321
322//
323// Same error message for all binary operations don't work.
324//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400325void TParseContext::binaryOpError(const TSourceLoc &line,
326 const char *op,
327 TString left,
328 TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000329{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000330 std::stringstream reasonStream;
331 reasonStream << "wrong operand types - no operation '" << op
332 << "' exists that takes a left-hand operand of type '" << left
333 << "' and a right operand of type '" << right
334 << "' (or there is no acceptable conversion)";
335 std::string reason = reasonStream.str();
336 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337}
338
Olli Etuaho856c4972016-08-08 11:38:39 +0300339void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
340 TPrecision precision,
341 TBasicType type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530342{
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400343 if (!mChecksPrecisionErrors)
Olli Etuaho383b7912016-08-05 11:22:59 +0300344 return;
Martin Radev70866b82016-07-22 15:27:42 +0300345
346 if (precision != EbpUndefined && !SupportsPrecision(type))
347 {
348 error(line, "illegal type for precision qualifier", getBasicString(type));
349 }
350
Olli Etuaho183d7e22015-11-20 15:59:09 +0200351 if (precision == EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530352 {
Olli Etuaho183d7e22015-11-20 15:59:09 +0200353 switch (type)
354 {
355 case EbtFloat:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400356 error(line, "No precision specified for (float)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300357 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200358 case EbtInt:
359 case EbtUInt:
360 UNREACHABLE(); // there's always a predeclared qualifier
Jamie Madillb98c3a82015-07-23 14:26:04 -0400361 error(line, "No precision specified (int)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300362 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200363 default:
jchen10cc2a10e2017-05-03 14:05:12 +0800364 if (IsOpaqueType(type))
Olli Etuaho183d7e22015-11-20 15:59:09 +0200365 {
jchen10cc2a10e2017-05-03 14:05:12 +0800366 error(line, "No precision specified", getBasicString(type));
Martin Radev2cc85b32016-08-05 16:22:53 +0300367 return;
368 }
Olli Etuaho183d7e22015-11-20 15:59:09 +0200369 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000370 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000371}
372
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000373// Both test and if necessary, spit out an error, to see if the node is really
374// an l-value that can be operated on this way.
Olli Etuaho856c4972016-08-08 11:38:39 +0300375bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000376{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500377 TIntermSymbol *symNode = node->getAsSymbolNode();
378 TIntermBinary *binaryNode = node->getAsBinaryNode();
Olli Etuahob6fa0432016-09-28 16:28:05 +0100379 TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
380
381 if (swizzleNode)
382 {
383 bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
384 if (ok && swizzleNode->hasDuplicateOffsets())
385 {
386 error(line, " l-value of swizzle cannot have duplicate components", op);
387 return false;
388 }
389 return ok;
390 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000391
Arun Patole7e7e68d2015-05-22 12:02:25 +0530392 if (binaryNode)
393 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400394 switch (binaryNode->getOp())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530395 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400396 case EOpIndexDirect:
397 case EOpIndexIndirect:
398 case EOpIndexDirectStruct:
399 case EOpIndexDirectInterfaceBlock:
Olli Etuaho856c4972016-08-08 11:38:39 +0300400 return checkCanBeLValue(line, op, binaryNode->getLeft());
Jamie Madillb98c3a82015-07-23 14:26:04 -0400401 default:
402 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000403 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000404 error(line, " l-value required", op);
Olli Etuaho8a176262016-08-16 14:23:01 +0300405 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000406 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000407
jchen10cc2a10e2017-05-03 14:05:12 +0800408 std::string message;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530409 switch (node->getQualifier())
410 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400411 case EvqConst:
412 message = "can't modify a const";
413 break;
414 case EvqConstReadOnly:
415 message = "can't modify a const";
416 break;
417 case EvqAttribute:
418 message = "can't modify an attribute";
419 break;
420 case EvqFragmentIn:
421 message = "can't modify an input";
422 break;
423 case EvqVertexIn:
424 message = "can't modify an input";
425 break;
426 case EvqUniform:
427 message = "can't modify a uniform";
428 break;
429 case EvqVaryingIn:
430 message = "can't modify a varying";
431 break;
432 case EvqFragCoord:
433 message = "can't modify gl_FragCoord";
434 break;
435 case EvqFrontFacing:
436 message = "can't modify gl_FrontFacing";
437 break;
438 case EvqPointCoord:
439 message = "can't modify gl_PointCoord";
440 break;
Martin Radevb0883602016-08-04 17:48:58 +0300441 case EvqNumWorkGroups:
442 message = "can't modify gl_NumWorkGroups";
443 break;
444 case EvqWorkGroupSize:
445 message = "can't modify gl_WorkGroupSize";
446 break;
447 case EvqWorkGroupID:
448 message = "can't modify gl_WorkGroupID";
449 break;
450 case EvqLocalInvocationID:
451 message = "can't modify gl_LocalInvocationID";
452 break;
453 case EvqGlobalInvocationID:
454 message = "can't modify gl_GlobalInvocationID";
455 break;
456 case EvqLocalInvocationIndex:
457 message = "can't modify gl_LocalInvocationIndex";
458 break;
Olli Etuaho7142f6c2017-05-05 17:07:26 +0300459 case EvqViewIDOVR:
460 message = "can't modify gl_ViewID_OVR";
461 break;
Martin Radev802abe02016-08-04 17:48:32 +0300462 case EvqComputeIn:
463 message = "can't modify work group size variable";
464 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400465 default:
466 //
467 // Type that can't be written to?
468 //
469 if (node->getBasicType() == EbtVoid)
470 {
471 message = "can't modify void";
472 }
jchen10cc2a10e2017-05-03 14:05:12 +0800473 if (IsOpaqueType(node->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -0400474 {
jchen10cc2a10e2017-05-03 14:05:12 +0800475 message = "can't modify a variable with type ";
476 message += getBasicString(node->getBasicType());
Martin Radev2cc85b32016-08-05 16:22:53 +0300477 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000478 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000479
jchen10cc2a10e2017-05-03 14:05:12 +0800480 if (message.empty() && binaryNode == 0 && symNode == 0)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530481 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000482 error(line, "l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000483
Olli Etuaho8a176262016-08-16 14:23:01 +0300484 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000485 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000486
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000487 //
488 // Everything else is okay, no error.
489 //
jchen10cc2a10e2017-05-03 14:05:12 +0800490 if (message.empty())
Olli Etuaho8a176262016-08-16 14:23:01 +0300491 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000492
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000493 //
494 // If we get here, we have an error and a message.
495 //
Arun Patole7e7e68d2015-05-22 12:02:25 +0530496 if (symNode)
497 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000498 const char *symbol = symNode->getSymbol().c_str();
499 std::stringstream reasonStream;
500 reasonStream << "l-value required (" << message << " \"" << symbol << "\")";
501 std::string reason = reasonStream.str();
502 error(line, reason.c_str(), op);
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000503 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530504 else
505 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000506 std::stringstream reasonStream;
507 reasonStream << "l-value required (" << message << ")";
508 std::string reason = reasonStream.str();
509 error(line, reason.c_str(), op);
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000510 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000511
Olli Etuaho8a176262016-08-16 14:23:01 +0300512 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000513}
514
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000515// Both test, and if necessary spit out an error, to see if the node is really
516// a constant.
Olli Etuaho856c4972016-08-08 11:38:39 +0300517void TParseContext::checkIsConst(TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000518{
Olli Etuaho383b7912016-08-05 11:22:59 +0300519 if (node->getQualifier() != EvqConst)
520 {
521 error(node->getLine(), "constant expression required", "");
522 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000523}
524
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000525// Both test, and if necessary spit out an error, to see if the node is really
526// an integer.
Olli Etuaho856c4972016-08-08 11:38:39 +0300527void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000528{
Olli Etuaho383b7912016-08-05 11:22:59 +0300529 if (!node->isScalarInt())
530 {
531 error(node->getLine(), "integer expression required", token);
532 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000533}
534
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000535// Both test, and if necessary spit out an error, to see if we are currently
536// globally scoped.
Qiankun Miaof69682b2016-08-16 14:50:42 +0800537bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000538{
Olli Etuaho856c4972016-08-08 11:38:39 +0300539 if (!symbolTable.atGlobalLevel())
Olli Etuaho383b7912016-08-05 11:22:59 +0300540 {
541 error(line, "only allowed at global scope", token);
Qiankun Miaof69682b2016-08-16 14:50:42 +0800542 return false;
Olli Etuaho383b7912016-08-05 11:22:59 +0300543 }
Qiankun Miaof69682b2016-08-16 14:50:42 +0800544 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000545}
546
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000547// For now, keep it simple: if it starts "gl_", it's reserved, independent
548// of scope. Except, if the symbol table is at the built-in push-level,
549// which is when we are parsing built-ins.
alokp@chromium.org613ef312010-07-21 18:54:22 +0000550// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
551// webgl shader.
Olli Etuaho856c4972016-08-08 11:38:39 +0300552bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000553{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530554 static const char *reservedErrMsg = "reserved built-in name";
555 if (!symbolTable.atBuiltInLevel())
556 {
557 if (identifier.compare(0, 3, "gl_") == 0)
558 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000559 error(line, reservedErrMsg, "gl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300560 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000561 }
Jamie Madillacb4b812016-11-07 13:50:29 -0500562 if (sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530563 {
564 if (identifier.compare(0, 6, "webgl_") == 0)
565 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000566 error(line, reservedErrMsg, "webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300567 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000568 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530569 if (identifier.compare(0, 7, "_webgl_") == 0)
570 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000571 error(line, reservedErrMsg, "_webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300572 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000573 }
574 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530575 if (identifier.find("__") != TString::npos)
576 {
577 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400578 "identifiers containing two consecutive underscores (__) are reserved as "
579 "possible future keywords",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530580 identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300581 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000582 }
583 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000584
Olli Etuaho8a176262016-08-16 14:23:01 +0300585 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000586}
587
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300588// Make sure the argument types are correct for constructing a specific type.
Olli Etuaho856c4972016-08-08 11:38:39 +0300589bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800590 const TIntermSequence *arguments,
Olli Etuaho856c4972016-08-08 11:38:39 +0300591 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000592{
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800593 if (arguments->empty())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530594 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200595 error(line, "constructor does not have any arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300596 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000597 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200598
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300599 for (TIntermNode *arg : *arguments)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530600 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300601 const TIntermTyped *argTyped = arg->getAsTyped();
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200602 ASSERT(argTyped != nullptr);
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300603 if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType()))
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200604 {
jchen10cc2a10e2017-05-03 14:05:12 +0800605 std::string reason("cannot convert a variable with type ");
606 reason += getBasicString(argTyped->getBasicType());
607 error(line, reason.c_str(), "constructor");
Martin Radev2cc85b32016-08-05 16:22:53 +0300608 return false;
609 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200610 if (argTyped->getBasicType() == EbtVoid)
611 {
612 error(line, "cannot convert a void", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300613 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200614 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000615 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000616
Olli Etuaho856c4972016-08-08 11:38:39 +0300617 if (type.isArray())
618 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300619 // The size of an unsized constructor should already have been determined.
620 ASSERT(!type.isUnsizedArray());
621 if (static_cast<size_t>(type.getArraySize()) != arguments->size())
622 {
623 error(line, "array constructor needs one argument per array element", "constructor");
624 return false;
625 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300626 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
627 // the array.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800628 for (TIntermNode *const &argNode : *arguments)
Olli Etuaho856c4972016-08-08 11:38:39 +0300629 {
630 const TType &argType = argNode->getAsTyped()->getType();
Jamie Madill34bf2d92017-02-06 13:40:59 -0500631 if (argType.isArray())
632 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300633 error(line, "constructing from a non-dereferenced array", "constructor");
Jamie Madill34bf2d92017-02-06 13:40:59 -0500634 return false;
635 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300636 if (!argType.sameElementType(type))
637 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000638 error(line, "Array constructor argument has an incorrect type", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300639 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300640 }
641 }
642 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300643 else if (type.getBasicType() == EbtStruct)
Olli Etuaho856c4972016-08-08 11:38:39 +0300644 {
645 const TFieldList &fields = type.getStruct()->fields();
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300646 if (fields.size() != arguments->size())
647 {
648 error(line,
649 "Number of constructor parameters does not match the number of structure fields",
650 "constructor");
651 return false;
652 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300653
654 for (size_t i = 0; i < fields.size(); i++)
655 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800656 if (i >= arguments->size() ||
657 (*arguments)[i]->getAsTyped()->getType() != *fields[i]->type())
Olli Etuaho856c4972016-08-08 11:38:39 +0300658 {
659 error(line, "Structure constructor arguments do not match structure fields",
Olli Etuaho4de340a2016-12-16 09:32:03 +0000660 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300661 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300662 }
663 }
664 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300665 else
666 {
667 // We're constructing a scalar, vector, or matrix.
668
669 // Note: It's okay to have too many components available, but not okay to have unused
670 // arguments. 'full' will go to true when enough args have been seen. If we loop again,
671 // there is an extra argument, so 'overFull' will become true.
672
673 size_t size = 0;
674 bool full = false;
675 bool overFull = false;
676 bool matrixArg = false;
677 for (TIntermNode *arg : *arguments)
678 {
679 const TIntermTyped *argTyped = arg->getAsTyped();
680 ASSERT(argTyped != nullptr);
681
Olli Etuaho487b63a2017-05-23 15:55:09 +0300682 if (argTyped->getBasicType() == EbtStruct)
683 {
684 error(line, "a struct cannot be used as a constructor argument for this type",
685 "constructor");
686 return false;
687 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300688 if (argTyped->getType().isArray())
689 {
690 error(line, "constructing from a non-dereferenced array", "constructor");
691 return false;
692 }
693 if (argTyped->getType().isMatrix())
694 {
695 matrixArg = true;
696 }
697
698 size += argTyped->getType().getObjectSize();
699 if (full)
700 {
701 overFull = true;
702 }
Olli Etuaho487b63a2017-05-23 15:55:09 +0300703 if (size >= type.getObjectSize())
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300704 {
705 full = true;
706 }
707 }
708
709 if (type.isMatrix() && matrixArg)
710 {
711 if (arguments->size() != 1)
712 {
713 error(line, "constructing matrix from matrix can only take one argument",
714 "constructor");
715 return false;
716 }
717 }
718 else
719 {
720 if (size != 1 && size < type.getObjectSize())
721 {
722 error(line, "not enough data provided for construction", "constructor");
723 return false;
724 }
725 if (overFull)
726 {
727 error(line, "too many arguments", "constructor");
728 return false;
729 }
730 }
731 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300732
Olli Etuaho8a176262016-08-16 14:23:01 +0300733 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000734}
735
Jamie Madillb98c3a82015-07-23 14:26:04 -0400736// This function checks to see if a void variable has been declared and raise an error message for
737// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000738//
739// returns true in case of an error
740//
Olli Etuaho856c4972016-08-08 11:38:39 +0300741bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400742 const TString &identifier,
743 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000744{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300745 if (type == EbtVoid)
746 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000747 error(line, "illegal use of type 'void'", identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300748 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300749 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000750
Olli Etuaho8a176262016-08-16 14:23:01 +0300751 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000752}
753
Jamie Madillb98c3a82015-07-23 14:26:04 -0400754// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300755// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300756void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000757{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530758 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
759 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000760 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530761 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000762}
763
Jamie Madillb98c3a82015-07-23 14:26:04 -0400764// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300765// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300766void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000767{
Martin Radev4a9cd802016-09-01 16:51:51 +0300768 if (pType.getBasicType() != EbtBool || pType.isAggregate())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530769 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000770 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530771 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000772}
773
jchen10cc2a10e2017-05-03 14:05:12 +0800774bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
775 const TTypeSpecifierNonArray &pType,
776 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000777{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530778 if (pType.type == EbtStruct)
779 {
Martin Radev2cc85b32016-08-05 16:22:53 +0300780 if (ContainsSampler(*pType.userDef))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530781 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000782 std::stringstream reasonStream;
783 reasonStream << reason << " (structure contains a sampler)";
784 std::string reasonStr = reasonStream.str();
785 error(line, reasonStr.c_str(), getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300786 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000787 }
jchen10cc2a10e2017-05-03 14:05:12 +0800788 // only samplers need to be checked from structs, since other opaque types can't be struct
789 // members.
Olli Etuaho8a176262016-08-16 14:23:01 +0300790 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530791 }
jchen10cc2a10e2017-05-03 14:05:12 +0800792 else if (IsOpaqueType(pType.type))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530793 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000794 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300795 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000796 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000797
Olli Etuaho8a176262016-08-16 14:23:01 +0300798 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000799}
800
Olli Etuaho856c4972016-08-08 11:38:39 +0300801void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
802 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400803{
804 if (pType.layoutQualifier.location != -1)
805 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400806 error(line, "location must only be specified for a single input or output variable",
807 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400808 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400809}
810
Olli Etuaho856c4972016-08-08 11:38:39 +0300811void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
812 const TLayoutQualifier &layoutQualifier)
813{
814 if (layoutQualifier.location != -1)
815 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000816 const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs";
817 if (mShaderVersion >= 310)
818 {
819 errorMsg =
820 "invalid layout qualifier: only valid on program inputs, outputs, and uniforms";
821 }
822 error(location, errorMsg, "location");
Olli Etuaho856c4972016-08-08 11:38:39 +0300823 }
824}
825
Martin Radev2cc85b32016-08-05 16:22:53 +0300826void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
827 TQualifier qualifier,
828 const TType &type)
829{
Martin Radev2cc85b32016-08-05 16:22:53 +0300830 ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
jchen10cc2a10e2017-05-03 14:05:12 +0800831 if (IsOpaqueType(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530832 {
jchen10cc2a10e2017-05-03 14:05:12 +0800833 error(line, "opaque types cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000834 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000835}
836
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000837// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300838unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000839{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530840 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000841
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200842 // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
843 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
844 // fold as array size.
845 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000846 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000847 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300848 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000849 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000850
Olli Etuaho856c4972016-08-08 11:38:39 +0300851 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400852
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000853 if (constant->getBasicType() == EbtUInt)
854 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300855 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000856 }
857 else
858 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300859 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000860
Olli Etuaho856c4972016-08-08 11:38:39 +0300861 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000862 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400863 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300864 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000865 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400866
Olli Etuaho856c4972016-08-08 11:38:39 +0300867 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -0400868 }
869
Olli Etuaho856c4972016-08-08 11:38:39 +0300870 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -0400871 {
872 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300873 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400874 }
875
876 // The size of arrays is restricted here to prevent issues further down the
877 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
878 // 4096 registers so this should be reasonable even for aggressively optimizable code.
879 const unsigned int sizeLimit = 65536;
880
Olli Etuaho856c4972016-08-08 11:38:39 +0300881 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -0400882 {
883 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300884 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000885 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300886
887 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000888}
889
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000890// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +0300891bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
892 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000893{
Olli Etuaho8a176262016-08-16 14:23:01 +0300894 if ((elementQualifier.qualifier == EvqAttribute) ||
895 (elementQualifier.qualifier == EvqVertexIn) ||
896 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +0300897 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400898 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300899 TType(elementQualifier).getQualifierString());
900 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000901 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000902
Olli Etuaho8a176262016-08-16 14:23:01 +0300903 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000904}
905
Olli Etuaho8a176262016-08-16 14:23:01 +0300906// See if this element type can be formed into an array.
907bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000908{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000909 //
910 // Can the type be an array?
911 //
Olli Etuaho8a176262016-08-16 14:23:01 +0300912 if (elementType.array)
Jamie Madill06145232015-05-13 13:10:01 -0400913 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300914 error(line, "cannot declare arrays of arrays",
915 TType(elementType).getCompleteString().c_str());
916 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000917 }
Olli Etuahocc36b982015-07-10 14:14:18 +0300918 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
919 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
920 // 4.3.4).
Martin Radev4a9cd802016-09-01 16:51:51 +0300921 if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
Olli Etuaho8a176262016-08-16 14:23:01 +0300922 sh::IsVarying(elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +0300923 {
924 error(line, "cannot declare arrays of structs of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300925 TType(elementType).getCompleteString().c_str());
926 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +0300927 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000928
Olli Etuaho8a176262016-08-16 14:23:01 +0300929 return true;
930}
931
932// Check if this qualified element type can be formed into an array.
933bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
934 const TPublicType &elementType)
935{
936 if (checkIsValidTypeForArray(indexLocation, elementType))
937 {
938 return checkIsValidQualifierForArray(indexLocation, elementType);
939 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000940 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000941}
942
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000943// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +0300944void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
945 const TString &identifier,
946 TPublicType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000947{
Olli Etuaho3739d232015-04-08 12:23:44 +0300948 ASSERT(type != nullptr);
949 if (type->qualifier == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000950 {
951 // Make the qualifier make sense.
Olli Etuaho3739d232015-04-08 12:23:44 +0300952 type->qualifier = EvqTemporary;
953
954 // Generate informative error messages for ESSL1.
955 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400956 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000957 {
Arun Patole7e7e68d2015-05-22 12:02:25 +0530958 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400959 "structures containing arrays may not be declared constant since they cannot be "
960 "initialized",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530961 identifier.c_str());
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000962 }
963 else
964 {
965 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
966 }
Olli Etuaho383b7912016-08-05 11:22:59 +0300967 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000968 }
Olli Etuaho376f1b52015-04-13 13:23:41 +0300969 if (type->isUnsizedArray())
970 {
971 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
Olli Etuaho376f1b52015-04-13 13:23:41 +0300972 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000973}
974
Olli Etuaho2935c582015-04-08 14:32:06 +0300975// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000976// and update the symbol table.
977//
Olli Etuaho2935c582015-04-08 14:32:06 +0300978// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000979//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400980bool TParseContext::declareVariable(const TSourceLoc &line,
981 const TString &identifier,
982 const TType &type,
Olli Etuaho2935c582015-04-08 14:32:06 +0300983 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000984{
Olli Etuaho2935c582015-04-08 14:32:06 +0300985 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000986
Olli Etuaho43364892017-02-13 16:00:12 +0000987 checkBindingIsValid(line, type);
988
Olli Etuaho856c4972016-08-08 11:38:39 +0300989 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000990
Olli Etuaho2935c582015-04-08 14:32:06 +0300991 // gl_LastFragData may be redeclared with a new precision qualifier
992 if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
993 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400994 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
995 symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Olli Etuaho856c4972016-08-08 11:38:39 +0300996 if (static_cast<int>(type.getArraySize()) == maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +0300997 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400998 if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +0300999 {
Olli Etuaho8a176262016-08-16 14:23:01 +03001000 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
Olli Etuaho2935c582015-04-08 14:32:06 +03001001 }
1002 }
1003 else
1004 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001005 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
1006 identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +03001007 return false;
1008 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001009 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001010
Olli Etuaho8a176262016-08-16 14:23:01 +03001011 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +03001012 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001013
Olli Etuaho2935c582015-04-08 14:32:06 +03001014 (*variable) = new TVariable(&identifier, type);
1015 if (!symbolTable.declare(*variable))
1016 {
1017 error(line, "redefinition", identifier.c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -04001018 *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +03001019 return false;
1020 }
1021
Olli Etuaho8a176262016-08-16 14:23:01 +03001022 if (!checkIsNonVoid(line, identifier, type.getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +03001023 return false;
1024
1025 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001026}
1027
Martin Radev70866b82016-07-22 15:27:42 +03001028void TParseContext::checkIsParameterQualifierValid(
1029 const TSourceLoc &line,
1030 const TTypeQualifierBuilder &typeQualifierBuilder,
1031 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301032{
Olli Etuaho77ba4082016-12-16 12:01:18 +00001033 TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03001034
1035 if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301036 {
Martin Radev2cc85b32016-08-05 16:22:53 +03001037 checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type);
1038 }
1039
1040 if (!IsImage(type->getBasicType()))
1041 {
Olli Etuaho43364892017-02-13 16:00:12 +00001042 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line);
Martin Radev2cc85b32016-08-05 16:22:53 +03001043 }
1044 else
1045 {
1046 type->setMemoryQualifier(typeQualifier.memoryQualifier);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001047 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001048
Martin Radev70866b82016-07-22 15:27:42 +03001049 type->setQualifier(typeQualifier.qualifier);
1050
1051 if (typeQualifier.precision != EbpUndefined)
1052 {
1053 type->setPrecision(typeQualifier.precision);
1054 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001055}
1056
Olli Etuaho856c4972016-08-08 11:38:39 +03001057bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001058{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001059 const TExtensionBehavior &extBehavior = extensionBehavior();
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001060 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
Arun Patole7e7e68d2015-05-22 12:02:25 +05301061 if (iter == extBehavior.end())
1062 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001063 error(line, "extension is not supported", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001064 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001065 }
zmo@google.comf5450912011-09-09 01:37:19 +00001066 // In GLSL ES, an extension's default behavior is "disable".
Arun Patole7e7e68d2015-05-22 12:02:25 +05301067 if (iter->second == EBhDisable || iter->second == EBhUndefined)
1068 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00001069 // TODO(oetuaho@nvidia.com): This is slightly hacky. Might be better if symbols could be
1070 // associated with more than one extension.
1071 if (extension == "GL_OVR_multiview")
1072 {
1073 return checkCanUseExtension(line, "GL_OVR_multiview2");
1074 }
Olli Etuaho4de340a2016-12-16 09:32:03 +00001075 error(line, "extension is disabled", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001076 return false;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001077 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301078 if (iter->second == EBhWarn)
1079 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001080 warning(line, "extension is being used", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001081 return true;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001082 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001083
Olli Etuaho8a176262016-08-16 14:23:01 +03001084 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001085}
1086
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001087// ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause
1088// compile-time or link-time errors are the same whether or not the declaration is empty".
1089// This function implements all the checks that are done on qualifiers regardless of if the
1090// declaration is empty.
1091void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier,
1092 const sh::TLayoutQualifier &layoutQualifier,
1093 const TSourceLoc &location)
1094{
1095 if (qualifier == EvqShared && !layoutQualifier.isEmpty())
1096 {
1097 error(location, "Shared memory declarations cannot have layout specified", "layout");
1098 }
1099
1100 if (layoutQualifier.matrixPacking != EmpUnspecified)
1101 {
1102 error(location, "layout qualifier only valid for interface blocks",
1103 getMatrixPackingString(layoutQualifier.matrixPacking));
1104 return;
1105 }
1106
1107 if (layoutQualifier.blockStorage != EbsUnspecified)
1108 {
1109 error(location, "layout qualifier only valid for interface blocks",
1110 getBlockStorageString(layoutQualifier.blockStorage));
1111 return;
1112 }
1113
1114 if (qualifier == EvqFragmentOut)
1115 {
1116 if (layoutQualifier.location != -1 && layoutQualifier.yuv == true)
1117 {
1118 error(location, "invalid layout qualifier combination", "yuv");
1119 return;
1120 }
1121 }
1122 else
1123 {
1124 checkYuvIsNotSpecified(location, layoutQualifier.yuv);
1125 }
1126
Olli Etuaho95468d12017-05-04 11:14:34 +03001127 // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous
1128 // parsing steps. So it needs to be checked here.
1129 if (isMultiviewExtensionEnabled() && mShaderVersion < 300 && qualifier == EvqVertexIn)
1130 {
1131 error(location, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
1132 }
1133
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001134 bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut;
1135 if (mShaderVersion >= 310 && qualifier == EvqUniform)
1136 {
1137 canHaveLocation = true;
1138 // We're not checking whether the uniform location is in range here since that depends on
1139 // the type of the variable.
1140 // The type can only be fully determined for non-empty declarations.
1141 }
1142 if (!canHaveLocation)
1143 {
1144 checkLocationIsNotSpecified(location, layoutQualifier);
1145 }
1146}
1147
jchen104cdac9e2017-05-08 11:01:20 +08001148void TParseContext::atomicCounterQualifierErrorCheck(const TPublicType &publicType,
1149 const TSourceLoc &location)
1150{
1151 if (publicType.precision != EbpHigh)
1152 {
1153 error(location, "Can only be highp", "atomic counter");
1154 }
1155 // dEQP enforces compile error if location is specified. See uniform_location.test.
1156 if (publicType.layoutQualifier.location != -1)
1157 {
1158 error(location, "location must not be set for atomic_uint", "layout");
1159 }
1160 if (publicType.layoutQualifier.binding == -1)
1161 {
1162 error(location, "no binding specified", "atomic counter");
1163 }
1164}
1165
Martin Radevb8b01222016-11-20 23:25:53 +02001166void TParseContext::emptyDeclarationErrorCheck(const TPublicType &publicType,
1167 const TSourceLoc &location)
1168{
1169 if (publicType.isUnsizedArray())
1170 {
1171 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1172 // error. It is assumed that this applies to empty declarations as well.
1173 error(location, "empty array declaration needs to specify a size", "");
1174 }
Martin Radevb8b01222016-11-20 23:25:53 +02001175}
1176
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001177// These checks are done for all declarations that are non-empty. They're done for non-empty
1178// declarations starting a declarator list, and declarators that follow an empty declaration.
1179void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
1180 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -04001181{
Olli Etuahofa33d582015-04-09 14:33:12 +03001182 switch (publicType.qualifier)
1183 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001184 case EvqVaryingIn:
1185 case EvqVaryingOut:
1186 case EvqAttribute:
1187 case EvqVertexIn:
1188 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +03001189 case EvqComputeIn:
Martin Radev4a9cd802016-09-01 16:51:51 +03001190 if (publicType.getBasicType() == EbtStruct)
Jamie Madillb98c3a82015-07-23 14:26:04 -04001191 {
1192 error(identifierLocation, "cannot be used with a structure",
1193 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +03001194 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001195 }
Olli Etuahofa33d582015-04-09 14:33:12 +03001196
Jamie Madillb98c3a82015-07-23 14:26:04 -04001197 default:
1198 break;
Olli Etuahofa33d582015-04-09 14:33:12 +03001199 }
jchen10cc2a10e2017-05-03 14:05:12 +08001200 std::string reason(getBasicString(publicType.getBasicType()));
1201 reason += "s must be uniform";
Jamie Madillb98c3a82015-07-23 14:26:04 -04001202 if (publicType.qualifier != EvqUniform &&
jchen10cc2a10e2017-05-03 14:05:12 +08001203 !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str()))
Martin Radev2cc85b32016-08-05 16:22:53 +03001204 {
1205 return;
1206 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001207
Andrei Volykhina5527072017-03-22 16:46:30 +03001208 if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal &&
1209 publicType.qualifier != EvqConst) &&
1210 publicType.getBasicType() == EbtYuvCscStandardEXT)
1211 {
1212 error(identifierLocation, "cannot be used with a yuvCscStandardEXT",
1213 getQualifierString(publicType.qualifier));
1214 return;
1215 }
1216
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001217 if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform)
1218 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001219 // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized.
1220 // But invalid shaders may still reach here with an unsized array declaration.
1221 if (!publicType.isUnsizedArray())
1222 {
1223 TType type(publicType);
1224 checkUniformLocationInRange(identifierLocation, type.getLocationCount(),
1225 publicType.layoutQualifier);
1226 }
1227 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001228
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001229 // check for layout qualifier issues
1230 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
Andrei Volykhina5527072017-03-22 16:46:30 +03001231
Martin Radev2cc85b32016-08-05 16:22:53 +03001232 if (IsImage(publicType.getBasicType()))
1233 {
1234
1235 switch (layoutQualifier.imageInternalFormat)
1236 {
1237 case EiifRGBA32F:
1238 case EiifRGBA16F:
1239 case EiifR32F:
1240 case EiifRGBA8:
1241 case EiifRGBA8_SNORM:
1242 if (!IsFloatImage(publicType.getBasicType()))
1243 {
1244 error(identifierLocation,
1245 "internal image format requires a floating image type",
1246 getBasicString(publicType.getBasicType()));
1247 return;
1248 }
1249 break;
1250 case EiifRGBA32I:
1251 case EiifRGBA16I:
1252 case EiifRGBA8I:
1253 case EiifR32I:
1254 if (!IsIntegerImage(publicType.getBasicType()))
1255 {
1256 error(identifierLocation,
1257 "internal image format requires an integer image type",
1258 getBasicString(publicType.getBasicType()));
1259 return;
1260 }
1261 break;
1262 case EiifRGBA32UI:
1263 case EiifRGBA16UI:
1264 case EiifRGBA8UI:
1265 case EiifR32UI:
1266 if (!IsUnsignedImage(publicType.getBasicType()))
1267 {
1268 error(identifierLocation,
1269 "internal image format requires an unsigned image type",
1270 getBasicString(publicType.getBasicType()));
1271 return;
1272 }
1273 break;
1274 case EiifUnspecified:
1275 error(identifierLocation, "layout qualifier", "No image internal format specified");
1276 return;
1277 default:
1278 error(identifierLocation, "layout qualifier", "unrecognized token");
1279 return;
1280 }
1281
1282 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
1283 switch (layoutQualifier.imageInternalFormat)
1284 {
1285 case EiifR32F:
1286 case EiifR32I:
1287 case EiifR32UI:
1288 break;
1289 default:
1290 if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
1291 {
1292 error(identifierLocation, "layout qualifier",
1293 "Except for images with the r32f, r32i and r32ui format qualifiers, "
1294 "image variables must be qualified readonly and/or writeonly");
1295 return;
1296 }
1297 break;
1298 }
1299 }
1300 else
1301 {
Olli Etuaho43364892017-02-13 16:00:12 +00001302 checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat);
Olli Etuaho43364892017-02-13 16:00:12 +00001303 checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
1304 }
jchen104cdac9e2017-05-08 11:01:20 +08001305
1306 if (IsAtomicCounter(publicType.getBasicType()))
1307 {
1308 atomicCounterQualifierErrorCheck(publicType, identifierLocation);
1309 }
1310 else
1311 {
1312 checkOffsetIsNotSpecified(identifierLocation, layoutQualifier.offset);
1313 }
Olli Etuaho43364892017-02-13 16:00:12 +00001314}
Martin Radev2cc85b32016-08-05 16:22:53 +03001315
Olli Etuaho43364892017-02-13 16:00:12 +00001316void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type)
1317{
1318 TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
1319 int arraySize = type.isArray() ? type.getArraySize() : 1;
1320 if (IsImage(type.getBasicType()))
1321 {
1322 checkImageBindingIsValid(identifierLocation, layoutQualifier.binding, arraySize);
1323 }
1324 else if (IsSampler(type.getBasicType()))
1325 {
1326 checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding, arraySize);
1327 }
jchen104cdac9e2017-05-08 11:01:20 +08001328 else if (IsAtomicCounter(type.getBasicType()))
1329 {
1330 checkAtomicCounterBindingIsValid(identifierLocation, layoutQualifier.binding);
1331 }
Olli Etuaho43364892017-02-13 16:00:12 +00001332 else
1333 {
1334 ASSERT(!IsOpaqueType(type.getBasicType()));
1335 checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
Martin Radev2cc85b32016-08-05 16:22:53 +03001336 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001337}
1338
Olli Etuaho856c4972016-08-08 11:38:39 +03001339void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1340 const TString &layoutQualifierName,
1341 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001342{
1343
1344 if (mShaderVersion < versionRequired)
1345 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001346 error(location, "invalid layout qualifier: not supported", layoutQualifierName.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03001347 }
1348}
1349
Olli Etuaho856c4972016-08-08 11:38:39 +03001350bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1351 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001352{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001353 const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
Martin Radev802abe02016-08-04 17:48:32 +03001354 for (size_t i = 0u; i < localSize.size(); ++i)
1355 {
1356 if (localSize[i] != -1)
1357 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001358 error(location,
1359 "invalid layout qualifier: only valid when used with 'in' in a compute shader "
1360 "global layout declaration",
1361 getWorkGroupSizeString(i));
Olli Etuaho8a176262016-08-16 14:23:01 +03001362 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001363 }
1364 }
1365
Olli Etuaho8a176262016-08-16 14:23:01 +03001366 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001367}
1368
Olli Etuaho43364892017-02-13 16:00:12 +00001369void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
Martin Radev2cc85b32016-08-05 16:22:53 +03001370 TLayoutImageInternalFormat internalFormat)
1371{
1372 if (internalFormat != EiifUnspecified)
1373 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001374 error(location, "invalid layout qualifier: only valid when used with images",
1375 getImageInternalFormatString(internalFormat));
Martin Radev2cc85b32016-08-05 16:22:53 +03001376 }
Olli Etuaho43364892017-02-13 16:00:12 +00001377}
1378
1379void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
1380{
1381 if (binding != -1)
1382 {
1383 error(location,
1384 "invalid layout qualifier: only valid when used with opaque types or blocks",
1385 "binding");
1386 }
1387}
1388
jchen104cdac9e2017-05-08 11:01:20 +08001389void TParseContext::checkOffsetIsNotSpecified(const TSourceLoc &location, int offset)
1390{
1391 if (offset != -1)
1392 {
1393 error(location, "invalid layout qualifier: only valid when used with atomic counters",
1394 "offset");
1395 }
1396}
1397
Olli Etuaho43364892017-02-13 16:00:12 +00001398void TParseContext::checkImageBindingIsValid(const TSourceLoc &location, int binding, int arraySize)
1399{
1400 // Expects arraySize to be 1 when setting binding for only a single variable.
1401 if (binding >= 0 && binding + arraySize > mMaxImageUnits)
1402 {
1403 error(location, "image binding greater than gl_MaxImageUnits", "binding");
1404 }
1405}
1406
1407void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location,
1408 int binding,
1409 int arraySize)
1410{
1411 // Expects arraySize to be 1 when setting binding for only a single variable.
1412 if (binding >= 0 && binding + arraySize > mMaxCombinedTextureImageUnits)
1413 {
1414 error(location, "sampler binding greater than maximum texture units", "binding");
1415 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001416}
1417
jchen10af713a22017-04-19 09:10:56 +08001418void TParseContext::checkBlockBindingIsValid(const TSourceLoc &location, int binding, int arraySize)
1419{
1420 int size = (arraySize == 0 ? 1 : arraySize);
1421 if (binding + size > mMaxUniformBufferBindings)
1422 {
1423 error(location, "interface block binding greater than MAX_UNIFORM_BUFFER_BINDINGS",
1424 "binding");
1425 }
1426}
jchen104cdac9e2017-05-08 11:01:20 +08001427void TParseContext::checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding)
1428{
1429 if (binding >= mMaxAtomicCounterBindings)
1430 {
1431 error(location, "atomic counter binding greater than gl_MaxAtomicCounterBindings",
1432 "binding");
1433 }
1434}
jchen10af713a22017-04-19 09:10:56 +08001435
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001436void TParseContext::checkUniformLocationInRange(const TSourceLoc &location,
1437 int objectLocationCount,
1438 const TLayoutQualifier &layoutQualifier)
1439{
1440 int loc = layoutQualifier.location;
1441 if (loc >= 0 && loc + objectLocationCount > mMaxUniformLocations)
1442 {
1443 error(location, "Uniform location out of range", "location");
1444 }
1445}
1446
Andrei Volykhina5527072017-03-22 16:46:30 +03001447void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv)
1448{
1449 if (yuv != false)
1450 {
1451 error(location, "invalid layout qualifier: only valid on program outputs", "yuv");
1452 }
1453}
1454
Olli Etuaho383b7912016-08-05 11:22:59 +03001455void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
Olli Etuaho856c4972016-08-08 11:38:39 +03001456 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001457{
1458 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1459 {
1460 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1461 if (qual == EvqOut || qual == EvqInOut)
1462 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001463 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho8a176262016-08-16 14:23:01 +03001464 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001465 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001466 error(argument->getLine(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00001467 "Constant value cannot be passed for 'out' or 'inout' parameters.",
Olli Etuahoec9232b2017-03-27 17:01:37 +03001468 fnCall->getFunctionSymbolInfo()->getName().c_str());
Olli Etuaho383b7912016-08-05 11:22:59 +03001469 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001470 }
1471 }
1472 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001473}
1474
Martin Radev70866b82016-07-22 15:27:42 +03001475void TParseContext::checkInvariantVariableQualifier(bool invariant,
1476 const TQualifier qualifier,
1477 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001478{
Martin Radev70866b82016-07-22 15:27:42 +03001479 if (!invariant)
1480 return;
1481
1482 if (mShaderVersion < 300)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001483 {
Martin Radev70866b82016-07-22 15:27:42 +03001484 // input variables in the fragment shader can be also qualified as invariant
1485 if (!sh::CanBeInvariantESSL1(qualifier))
1486 {
1487 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1488 }
1489 }
1490 else
1491 {
1492 if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
1493 {
1494 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1495 }
Olli Etuaho37ad4742015-04-27 13:18:50 +03001496 }
1497}
1498
Arun Patole7e7e68d2015-05-22 12:02:25 +05301499bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001500{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001501 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001502 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1503 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001504}
1505
Arun Patole7e7e68d2015-05-22 12:02:25 +05301506bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001507{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001508 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001509}
1510
Jamie Madillb98c3a82015-07-23 14:26:04 -04001511void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1512 const char *extName,
1513 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001514{
1515 pp::SourceLocation srcLoc;
1516 srcLoc.file = loc.first_file;
1517 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001518 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001519}
1520
Jamie Madillb98c3a82015-07-23 14:26:04 -04001521void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1522 const char *name,
1523 const char *value,
1524 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001525{
1526 pp::SourceLocation srcLoc;
1527 srcLoc.file = loc.first_file;
1528 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001529 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001530}
1531
Martin Radev4c4c8e72016-08-04 12:25:34 +03001532sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
Martin Radev802abe02016-08-04 17:48:32 +03001533{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001534 sh::WorkGroupSize result;
Martin Radev802abe02016-08-04 17:48:32 +03001535 for (size_t i = 0u; i < result.size(); ++i)
1536 {
1537 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1538 {
1539 result[i] = 1;
1540 }
1541 else
1542 {
1543 result[i] = mComputeShaderLocalSize[i];
1544 }
1545 }
1546 return result;
1547}
1548
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001549/////////////////////////////////////////////////////////////////////////////////
1550//
1551// Non-Errors.
1552//
1553/////////////////////////////////////////////////////////////////////////////////
1554
Jamie Madill5c097022014-08-20 16:38:32 -04001555const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1556 const TString *name,
1557 const TSymbol *symbol)
1558{
Yunchao Hed7297bf2017-04-19 15:27:10 +08001559 const TVariable *variable = nullptr;
Jamie Madill5c097022014-08-20 16:38:32 -04001560
1561 if (!symbol)
1562 {
1563 error(location, "undeclared identifier", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001564 }
1565 else if (!symbol->isVariable())
1566 {
1567 error(location, "variable expected", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001568 }
1569 else
1570 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001571 variable = static_cast<const TVariable *>(symbol);
Jamie Madill5c097022014-08-20 16:38:32 -04001572
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001573 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
Olli Etuaho383b7912016-08-05 11:22:59 +03001574 !variable->getExtension().empty())
Jamie Madill5c097022014-08-20 16:38:32 -04001575 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001576 checkCanUseExtension(location, variable->getExtension());
Jamie Madill5c097022014-08-20 16:38:32 -04001577 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001578
1579 // Reject shaders using both gl_FragData and gl_FragColor
1580 TQualifier qualifier = variable->getType().getQualifier();
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001581 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001582 {
1583 mUsesFragData = true;
1584 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001585 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001586 {
1587 mUsesFragColor = true;
1588 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001589 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1590 {
1591 mUsesSecondaryOutputs = true;
1592 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001593
1594 // This validation is not quite correct - it's only an error to write to
1595 // both FragData and FragColor. For simplicity, and because users shouldn't
1596 // be rewarded for reading from undefined varaibles, return an error
1597 // if they are both referenced, rather than assigned.
1598 if (mUsesFragData && mUsesFragColor)
1599 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001600 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1601 if (mUsesSecondaryOutputs)
1602 {
1603 errorMessage =
1604 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1605 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1606 }
1607 error(location, errorMessage, name->c_str());
Jamie Madill14e95b32015-05-07 10:10:41 -04001608 }
Martin Radevb0883602016-08-04 17:48:58 +03001609
1610 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1611 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1612 qualifier == EvqWorkGroupSize)
1613 {
1614 error(location,
1615 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1616 "gl_WorkGroupSize");
1617 }
Jamie Madill5c097022014-08-20 16:38:32 -04001618 }
1619
1620 if (!variable)
1621 {
1622 TType type(EbtFloat, EbpUndefined);
1623 TVariable *fakeVariable = new TVariable(name, type);
1624 symbolTable.declare(fakeVariable);
1625 variable = fakeVariable;
1626 }
1627
1628 return variable;
1629}
1630
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001631TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1632 const TString *name,
1633 const TSymbol *symbol)
1634{
1635 const TVariable *variable = getNamedVariable(location, name, symbol);
1636
Olli Etuaho09b04a22016-12-15 13:30:26 +00001637 if (variable->getType().getQualifier() == EvqViewIDOVR && IsWebGLBasedSpec(mShaderSpec) &&
1638 mShaderType == GL_FRAGMENT_SHADER && !isExtensionEnabled("GL_OVR_multiview2"))
1639 {
1640 // WEBGL_multiview spec
1641 error(location, "Need to enable OVR_multiview2 to use gl_ViewID_OVR in fragment shader",
1642 "gl_ViewID_OVR");
1643 }
1644
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001645 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001646 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001647 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001648 return intermediate.addConstantUnion(constArray, variable->getType(), location);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001649 }
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001650 else if (variable->getType().getQualifier() == EvqWorkGroupSize &&
1651 mComputeShaderLocalSizeDeclared)
1652 {
1653 // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
1654 // needs to be added to the AST as a constant and not as a symbol.
1655 sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
1656 TConstantUnion *constArray = new TConstantUnion[3];
1657 for (size_t i = 0; i < 3; ++i)
1658 {
1659 constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
1660 }
1661
1662 ASSERT(variable->getType().getBasicType() == EbtUInt);
1663 ASSERT(variable->getType().getObjectSize() == 3);
1664
1665 TType type(variable->getType());
1666 type.setQualifier(EvqConst);
1667 return intermediate.addConstantUnion(constArray, type, location);
1668 }
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001669 else
1670 {
1671 return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
1672 variable->getType(), location);
1673 }
1674}
1675
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001676// Initializers show up in several places in the grammar. Have one set of
1677// code to handle them here.
1678//
Olli Etuaho914b79a2017-06-19 16:03:19 +03001679// Returns true on success.
Jamie Madillb98c3a82015-07-23 14:26:04 -04001680bool TParseContext::executeInitializer(const TSourceLoc &line,
1681 const TString &identifier,
1682 const TPublicType &pType,
1683 TIntermTyped *initializer,
Olli Etuaho13389b62016-10-16 11:48:18 +01001684 TIntermBinary **initNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001685{
Olli Etuaho13389b62016-10-16 11:48:18 +01001686 ASSERT(initNode != nullptr);
1687 ASSERT(*initNode == nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001688 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001689
Olli Etuaho2935c582015-04-08 14:32:06 +03001690 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001691 if (type.isUnsizedArray())
1692 {
Olli Etuaho02bd82c2016-11-03 10:29:43 +00001693 // We have not checked yet whether the initializer actually is an array or not.
1694 if (initializer->isArray())
1695 {
1696 type.setArraySize(initializer->getArraySize());
1697 }
1698 else
1699 {
1700 // Having a non-array initializer for an unsized array will result in an error later,
1701 // so we don't generate an error message here.
1702 type.setArraySize(1u);
1703 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03001704 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001705 if (!declareVariable(line, identifier, type, &variable))
1706 {
Olli Etuaho914b79a2017-06-19 16:03:19 +03001707 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001708 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001709
Olli Etuahob0c645e2015-05-12 14:25:36 +03001710 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001711 if (symbolTable.atGlobalLevel() &&
1712 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001713 {
1714 // Error message does not completely match behavior with ESSL 1.00, but
1715 // we want to steer developers towards only using constant expressions.
1716 error(line, "global variable initializers must be constant expressions", "=");
Olli Etuaho914b79a2017-06-19 16:03:19 +03001717 return false;
Olli Etuahob0c645e2015-05-12 14:25:36 +03001718 }
1719 if (globalInitWarning)
1720 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001721 warning(
1722 line,
1723 "global variable initializers should be constant expressions "
1724 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1725 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001726 }
1727
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001728 //
1729 // identifier must be of type constant, a global, or a temporary
1730 //
1731 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301732 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1733 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001734 error(line, " cannot initialize this type of qualifier ",
1735 variable->getType().getQualifierString());
Olli Etuaho914b79a2017-06-19 16:03:19 +03001736 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001737 }
1738 //
1739 // test for and propagate constant
1740 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001741
Arun Patole7e7e68d2015-05-22 12:02:25 +05301742 if (qualifier == EvqConst)
1743 {
1744 if (qualifier != initializer->getType().getQualifier())
1745 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001746 std::stringstream reasonStream;
1747 reasonStream << "assigning non-constant to '" << variable->getType().getCompleteString()
1748 << "'";
1749 std::string reason = reasonStream.str();
1750 error(line, reason.c_str(), "=");
alokp@chromium.org58e54292010-08-24 21:40:03 +00001751 variable->getType().setQualifier(EvqTemporary);
Olli Etuaho914b79a2017-06-19 16:03:19 +03001752 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001753 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301754 if (type != initializer->getType())
1755 {
1756 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001757 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001758 variable->getType().setQualifier(EvqTemporary);
Olli Etuaho914b79a2017-06-19 16:03:19 +03001759 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001760 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001761
1762 // Save the constant folded value to the variable if possible. For example array
1763 // initializers are not folded, since that way copying the array literal to multiple places
1764 // in the shader is avoided.
1765 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1766 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301767 if (initializer->getAsConstantUnion())
1768 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001769 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuaho914b79a2017-06-19 16:03:19 +03001770 ASSERT(*initNode == nullptr);
1771 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301772 }
1773 else if (initializer->getAsSymbolNode())
1774 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001775 const TSymbol *symbol =
1776 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1777 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001778
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001779 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001780 if (constArray)
1781 {
1782 variable->shareConstPointer(constArray);
Olli Etuaho914b79a2017-06-19 16:03:19 +03001783 ASSERT(*initNode == nullptr);
1784 return true;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001785 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001786 }
1787 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001788
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001789 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1790 variable->getUniqueId(), variable->getName(), variable->getType(), line);
Olli Etuaho13389b62016-10-16 11:48:18 +01001791 *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1792 if (*initNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001793 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001794 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
Olli Etuaho914b79a2017-06-19 16:03:19 +03001795 return false;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001796 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001797
Olli Etuaho914b79a2017-06-19 16:03:19 +03001798 return true;
1799}
1800
1801TIntermNode *TParseContext::addConditionInitializer(const TPublicType &pType,
1802 const TString &identifier,
1803 TIntermTyped *initializer,
1804 const TSourceLoc &loc)
1805{
1806 checkIsScalarBool(loc, pType);
1807 TIntermBinary *initNode = nullptr;
1808 if (executeInitializer(loc, identifier, pType, initializer, &initNode))
1809 {
1810 // The initializer is valid. The init condition needs to have a node - either the
1811 // initializer node, or a constant node in case the initialized variable is const and won't
1812 // be recorded in the AST.
1813 if (initNode == nullptr)
1814 {
1815 return initializer;
1816 }
1817 else
1818 {
1819 TIntermDeclaration *declaration = new TIntermDeclaration();
1820 declaration->appendDeclarator(initNode);
1821 return declaration;
1822 }
1823 }
1824 return nullptr;
1825}
1826
1827TIntermNode *TParseContext::addLoop(TLoopType type,
1828 TIntermNode *init,
1829 TIntermNode *cond,
1830 TIntermTyped *expr,
1831 TIntermNode *body,
1832 const TSourceLoc &line)
1833{
1834 TIntermNode *node = nullptr;
1835 TIntermTyped *typedCond = nullptr;
1836 if (cond)
1837 {
1838 typedCond = cond->getAsTyped();
1839 }
1840 if (cond == nullptr || typedCond)
1841 {
1842 node = new TIntermLoop(type, init, typedCond, expr, TIntermediate::EnsureBlock(body));
1843 node->setLine(line);
1844 return node;
1845 }
1846
1847 TIntermDeclaration *declaration = cond->getAsDeclarationNode();
1848 ASSERT(declaration);
1849 TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode();
1850 ASSERT(declarator->getLeft()->getAsSymbolNode());
1851
1852 // The condition is a declaration. In the AST representation we don't support declarations as
1853 // loop conditions. Wrap the loop to a block that declares the condition variable and contains
1854 // the loop.
1855 TIntermBlock *block = new TIntermBlock();
1856
1857 TIntermDeclaration *declareCondition = new TIntermDeclaration();
1858 declareCondition->appendDeclarator(declarator->getLeft()->deepCopy());
1859 block->appendStatement(declareCondition);
1860
1861 TIntermBinary *conditionInit = new TIntermBinary(EOpAssign, declarator->getLeft()->deepCopy(),
1862 declarator->getRight()->deepCopy());
1863 TIntermLoop *loop =
1864 new TIntermLoop(type, init, conditionInit, expr, TIntermediate::EnsureBlock(body));
1865 block->appendStatement(loop);
1866 loop->setLine(line);
1867 block->setLine(line);
1868 return block;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001869}
1870
Olli Etuaho0e3aee32016-10-27 12:56:38 +01001871void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
1872{
1873 checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
1874 typeSpecifier->getBasicType());
1875
1876 if (mShaderVersion < 300 && typeSpecifier->array)
1877 {
1878 error(typeSpecifier->getLine(), "not supported", "first-class array");
1879 typeSpecifier->clearArrayness();
1880 }
1881}
1882
Martin Radev70866b82016-07-22 15:27:42 +03001883TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301884 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001885{
Olli Etuaho77ba4082016-12-16 12:01:18 +00001886 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001887
Martin Radev70866b82016-07-22 15:27:42 +03001888 TPublicType returnType = typeSpecifier;
1889 returnType.qualifier = typeQualifier.qualifier;
1890 returnType.invariant = typeQualifier.invariant;
1891 returnType.layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03001892 returnType.memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03001893 returnType.precision = typeSpecifier.precision;
1894
1895 if (typeQualifier.precision != EbpUndefined)
1896 {
1897 returnType.precision = typeQualifier.precision;
1898 }
1899
Martin Radev4a9cd802016-09-01 16:51:51 +03001900 checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
1901 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03001902
Martin Radev4a9cd802016-09-01 16:51:51 +03001903 checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
1904 typeSpecifier.getLine());
Martin Radev70866b82016-07-22 15:27:42 +03001905
Martin Radev4a9cd802016-09-01 16:51:51 +03001906 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001907
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001908 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001909 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001910 if (typeSpecifier.array)
1911 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001912 error(typeSpecifier.getLine(), "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001913 returnType.clearArrayness();
1914 }
1915
Martin Radev70866b82016-07-22 15:27:42 +03001916 if (returnType.qualifier == EvqAttribute &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001917 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001918 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001919 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001920 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001921 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001922
Martin Radev70866b82016-07-22 15:27:42 +03001923 if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001924 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001925 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001926 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001927 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001928 }
1929 }
1930 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001931 {
Martin Radev70866b82016-07-22 15:27:42 +03001932 if (!returnType.layoutQualifier.isEmpty())
Olli Etuahoabb0c382015-07-13 12:01:12 +03001933 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001934 checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03001935 }
Martin Radev70866b82016-07-22 15:27:42 +03001936 if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
1937 returnType.qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001938 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001939 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
1940 typeSpecifier.getLine());
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001941 }
Martin Radev70866b82016-07-22 15:27:42 +03001942 if (returnType.qualifier == EvqComputeIn)
Martin Radev802abe02016-08-04 17:48:32 +03001943 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001944 error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
Martin Radev802abe02016-08-04 17:48:32 +03001945 "in");
Martin Radev802abe02016-08-04 17:48:32 +03001946 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001947 }
1948
1949 return returnType;
1950}
1951
Olli Etuaho856c4972016-08-08 11:38:39 +03001952void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1953 const TPublicType &type,
1954 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03001955{
1956 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
Martin Radev4a9cd802016-09-01 16:51:51 +03001957 if (type.getBasicType() == EbtBool)
Olli Etuahocc36b982015-07-10 14:14:18 +03001958 {
1959 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001960 }
1961
1962 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1963 switch (qualifier)
1964 {
1965 case EvqVertexIn:
1966 // ESSL 3.00 section 4.3.4
1967 if (type.array)
1968 {
1969 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001970 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001971 // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03001972 return;
1973 case EvqFragmentOut:
1974 // ESSL 3.00 section 4.3.6
Martin Radev4a9cd802016-09-01 16:51:51 +03001975 if (type.typeSpecifierNonArray.isMatrix())
Olli Etuahocc36b982015-07-10 14:14:18 +03001976 {
1977 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001978 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001979 // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03001980 return;
1981 default:
1982 break;
1983 }
1984
1985 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1986 // restrictions.
1987 bool typeContainsIntegers =
Martin Radev4a9cd802016-09-01 16:51:51 +03001988 (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
1989 type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
Olli Etuahocc36b982015-07-10 14:14:18 +03001990 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1991 {
1992 error(qualifierLocation, "must use 'flat' interpolation here",
1993 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001994 }
1995
Martin Radev4a9cd802016-09-01 16:51:51 +03001996 if (type.getBasicType() == EbtStruct)
Olli Etuahocc36b982015-07-10 14:14:18 +03001997 {
1998 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1999 // These restrictions are only implied by the ESSL 3.00 spec, but
2000 // the ESSL 3.10 spec lists these restrictions explicitly.
2001 if (type.array)
2002 {
2003 error(qualifierLocation, "cannot be an array of structures",
2004 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002005 }
2006 if (type.isStructureContainingArrays())
2007 {
2008 error(qualifierLocation, "cannot be a structure containing an array",
2009 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002010 }
2011 if (type.isStructureContainingType(EbtStruct))
2012 {
2013 error(qualifierLocation, "cannot be a structure containing a structure",
2014 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002015 }
2016 if (type.isStructureContainingType(EbtBool))
2017 {
2018 error(qualifierLocation, "cannot be a structure containing a bool",
2019 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002020 }
2021 }
2022}
2023
Martin Radev2cc85b32016-08-05 16:22:53 +03002024void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
2025{
2026 if (qualifier.getType() == QtStorage)
2027 {
2028 const TStorageQualifierWrapper &storageQualifier =
2029 static_cast<const TStorageQualifierWrapper &>(qualifier);
2030 if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
2031 !symbolTable.atGlobalLevel())
2032 {
2033 error(storageQualifier.getLine(),
2034 "Local variables can only use the const storage qualifier.",
2035 storageQualifier.getQualifierString().c_str());
2036 }
2037 }
2038}
2039
Olli Etuaho43364892017-02-13 16:00:12 +00002040void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
Martin Radev2cc85b32016-08-05 16:22:53 +03002041 const TSourceLoc &location)
2042{
2043 if (memoryQualifier.readonly)
2044 {
2045 error(location, "Only allowed with images.", "readonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03002046 }
2047 if (memoryQualifier.writeonly)
2048 {
2049 error(location, "Only allowed with images.", "writeonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03002050 }
Martin Radev049edfa2016-11-11 14:35:37 +02002051 if (memoryQualifier.coherent)
2052 {
2053 error(location, "Only allowed with images.", "coherent");
Martin Radev049edfa2016-11-11 14:35:37 +02002054 }
2055 if (memoryQualifier.restrictQualifier)
2056 {
2057 error(location, "Only allowed with images.", "restrict");
Martin Radev049edfa2016-11-11 14:35:37 +02002058 }
2059 if (memoryQualifier.volatileQualifier)
2060 {
2061 error(location, "Only allowed with images.", "volatile");
Martin Radev049edfa2016-11-11 14:35:37 +02002062 }
Martin Radev2cc85b32016-08-05 16:22:53 +03002063}
2064
jchen104cdac9e2017-05-08 11:01:20 +08002065// Make sure there is no offset overlapping, and store the newly assigned offset to "type" in
2066// intermediate tree.
2067void TParseContext::checkAtomicCounterOffsetIsNotOverlapped(TPublicType &publicType,
2068 size_t size,
2069 bool forceAppend,
2070 const TSourceLoc &loc,
2071 TType &type)
2072{
2073 auto &bindingState = mAtomicCounterBindingStates[publicType.layoutQualifier.binding];
2074 int offset;
2075 if (publicType.layoutQualifier.offset == -1 || forceAppend)
2076 {
2077 offset = bindingState.appendSpan(size);
2078 }
2079 else
2080 {
2081 offset = bindingState.insertSpan(publicType.layoutQualifier.offset, size);
2082 }
2083 if (offset == -1)
2084 {
2085 error(loc, "Offset overlapping", "atomic counter");
2086 return;
2087 }
2088 TLayoutQualifier qualifier = type.getLayoutQualifier();
2089 qualifier.offset = offset;
2090 type.setLayoutQualifier(qualifier);
2091}
2092
Olli Etuaho13389b62016-10-16 11:48:18 +01002093TIntermDeclaration *TParseContext::parseSingleDeclaration(
2094 TPublicType &publicType,
2095 const TSourceLoc &identifierOrTypeLocation,
2096 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04002097{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07002098 TType type(publicType);
2099 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
2100 mDirectiveHandler.pragma().stdgl.invariantAll)
2101 {
2102 TQualifier qualifier = type.getQualifier();
2103
2104 // The directive handler has already taken care of rejecting invalid uses of this pragma
2105 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
2106 // affected variable declarations:
2107 //
2108 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
2109 // elsewhere, in TranslatorGLSL.)
2110 //
2111 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
2112 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
2113 // the way this is currently implemented we have to enable this compiler option before
2114 // parsing the shader and determining the shading language version it uses. If this were
2115 // implemented as a post-pass, the workaround could be more targeted.
2116 //
2117 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
2118 // the specification, but there are desktop OpenGL drivers that expect that this is the
2119 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
2120 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
2121 {
2122 type.setInvariant(true);
2123 }
2124 }
2125
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002126 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2127 identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002128
Olli Etuahobab4c082015-04-24 16:38:49 +03002129 bool emptyDeclaration = (identifier == "");
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002130 mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration;
Olli Etuahofa33d582015-04-09 14:33:12 +03002131
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002132 TIntermSymbol *symbol = nullptr;
Olli Etuahobab4c082015-04-24 16:38:49 +03002133 if (emptyDeclaration)
2134 {
Martin Radevb8b01222016-11-20 23:25:53 +02002135 emptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002136 // In most cases we don't need to create a symbol node for an empty declaration.
2137 // But if the empty declaration is declaring a struct type, the symbol node will store that.
2138 if (type.getBasicType() == EbtStruct)
2139 {
2140 symbol = intermediate.addSymbol(0, "", type, identifierOrTypeLocation);
2141 }
jchen104cdac9e2017-05-08 11:01:20 +08002142 else if (IsAtomicCounter(publicType.getBasicType()))
2143 {
2144 setAtomicCounterBindingDefaultOffset(publicType, identifierOrTypeLocation);
2145 }
Olli Etuahobab4c082015-04-24 16:38:49 +03002146 }
2147 else
Jamie Madill60ed9812013-06-06 11:56:46 -04002148 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002149 nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002150
Olli Etuaho856c4972016-08-08 11:38:39 +03002151 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002152
jchen104cdac9e2017-05-08 11:01:20 +08002153 if (IsAtomicCounter(publicType.getBasicType()))
2154 {
2155
2156 checkAtomicCounterOffsetIsNotOverlapped(publicType, kAtomicCounterSize, false,
2157 identifierOrTypeLocation, type);
2158 }
2159
Olli Etuaho2935c582015-04-08 14:32:06 +03002160 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07002161 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04002162
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002163 if (variable)
Olli Etuaho13389b62016-10-16 11:48:18 +01002164 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002165 symbol = intermediate.addSymbol(variable->getUniqueId(), identifier, type,
2166 identifierOrTypeLocation);
Olli Etuaho13389b62016-10-16 11:48:18 +01002167 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002168 }
2169
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002170 TIntermDeclaration *declaration = new TIntermDeclaration();
2171 declaration->setLine(identifierOrTypeLocation);
2172 if (symbol)
2173 {
2174 declaration->appendDeclarator(symbol);
2175 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002176 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002177}
2178
Olli Etuaho13389b62016-10-16 11:48:18 +01002179TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
2180 const TSourceLoc &identifierLocation,
2181 const TString &identifier,
2182 const TSourceLoc &indexLocation,
2183 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04002184{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002185 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002186
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002187 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2188 identifierLocation);
2189
2190 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002191
Olli Etuaho856c4972016-08-08 11:38:39 +03002192 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002193
Olli Etuaho8a176262016-08-16 14:23:01 +03002194 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002195
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002196 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002197
Olli Etuaho856c4972016-08-08 11:38:39 +03002198 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002199 // Make the type an array even if size check failed.
2200 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2201 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04002202
jchen104cdac9e2017-05-08 11:01:20 +08002203 if (IsAtomicCounter(publicType.getBasicType()))
2204 {
2205 checkAtomicCounterOffsetIsNotOverlapped(publicType, kAtomicCounterArrayStride * size, false,
2206 identifierLocation, arrayType);
2207 }
2208
Olli Etuaho2935c582015-04-08 14:32:06 +03002209 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002210 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04002211
Olli Etuaho13389b62016-10-16 11:48:18 +01002212 TIntermDeclaration *declaration = new TIntermDeclaration();
2213 declaration->setLine(identifierLocation);
2214
Olli Etuahoe7847b02015-03-16 11:56:12 +02002215 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002216 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002217 {
Jamie Madill60ed9812013-06-06 11:56:46 -04002218 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002219 declaration->appendDeclarator(symbol);
2220 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002221
Olli Etuaho13389b62016-10-16 11:48:18 +01002222 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002223}
2224
Olli Etuaho13389b62016-10-16 11:48:18 +01002225TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
2226 const TSourceLoc &identifierLocation,
2227 const TString &identifier,
2228 const TSourceLoc &initLocation,
2229 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04002230{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002231 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002232
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002233 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2234 identifierLocation);
2235
2236 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002237
Olli Etuaho13389b62016-10-16 11:48:18 +01002238 TIntermDeclaration *declaration = new TIntermDeclaration();
2239 declaration->setLine(identifierLocation);
2240
2241 TIntermBinary *initNode = nullptr;
Olli Etuaho914b79a2017-06-19 16:03:19 +03002242 if (executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04002243 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002244 if (initNode)
2245 {
2246 declaration->appendDeclarator(initNode);
2247 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002248 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002249 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002250}
2251
Olli Etuaho13389b62016-10-16 11:48:18 +01002252TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
Jamie Madillb98c3a82015-07-23 14:26:04 -04002253 TPublicType &publicType,
2254 const TSourceLoc &identifierLocation,
2255 const TString &identifier,
2256 const TSourceLoc &indexLocation,
2257 TIntermTyped *indexExpression,
2258 const TSourceLoc &initLocation,
2259 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002260{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002261 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002262
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002263 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2264 identifierLocation);
2265
2266 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002267
Olli Etuaho8a176262016-08-16 14:23:01 +03002268 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002269
2270 TPublicType arrayType(publicType);
2271
Olli Etuaho856c4972016-08-08 11:38:39 +03002272 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002273 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2274 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002275 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002276 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002277 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002278 }
2279 // Make the type an array even if size check failed.
2280 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2281 arrayType.setArraySize(size);
2282
Olli Etuaho13389b62016-10-16 11:48:18 +01002283 TIntermDeclaration *declaration = new TIntermDeclaration();
2284 declaration->setLine(identifierLocation);
2285
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002286 // initNode will correspond to the whole of "type b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002287 TIntermBinary *initNode = nullptr;
Olli Etuaho914b79a2017-06-19 16:03:19 +03002288 if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002289 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002290 if (initNode)
2291 {
2292 declaration->appendDeclarator(initNode);
2293 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002294 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002295
2296 return declaration;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002297}
2298
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002299TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
Martin Radev70866b82016-07-22 15:27:42 +03002300 const TTypeQualifierBuilder &typeQualifierBuilder,
2301 const TSourceLoc &identifierLoc,
2302 const TString *identifier,
2303 const TSymbol *symbol)
Jamie Madill47e3ec02014-08-20 16:38:33 -04002304{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002305 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002306
Martin Radev70866b82016-07-22 15:27:42 +03002307 if (!typeQualifier.invariant)
2308 {
2309 error(identifierLoc, "Expected invariant", identifier->c_str());
2310 return nullptr;
2311 }
2312 if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
2313 {
2314 return nullptr;
2315 }
Jamie Madill47e3ec02014-08-20 16:38:33 -04002316 if (!symbol)
2317 {
2318 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002319 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04002320 }
Martin Radev70866b82016-07-22 15:27:42 +03002321 if (!IsQualifierUnspecified(typeQualifier.qualifier))
Jamie Madill47e3ec02014-08-20 16:38:33 -04002322 {
Martin Radev70866b82016-07-22 15:27:42 +03002323 error(identifierLoc, "invariant declaration specifies qualifier",
2324 getQualifierString(typeQualifier.qualifier));
Jamie Madill47e3ec02014-08-20 16:38:33 -04002325 }
Martin Radev70866b82016-07-22 15:27:42 +03002326 if (typeQualifier.precision != EbpUndefined)
2327 {
2328 error(identifierLoc, "invariant declaration specifies precision",
2329 getPrecisionString(typeQualifier.precision));
2330 }
2331 if (!typeQualifier.layoutQualifier.isEmpty())
2332 {
2333 error(identifierLoc, "invariant declaration specifies layout", "'layout'");
2334 }
2335
2336 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
2337 ASSERT(variable);
2338 const TType &type = variable->getType();
2339
2340 checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
2341 typeQualifier.line);
Olli Etuaho43364892017-02-13 16:00:12 +00002342 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev70866b82016-07-22 15:27:42 +03002343
2344 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
2345
2346 TIntermSymbol *intermSymbol =
2347 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
2348
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002349 return new TIntermInvariantDeclaration(intermSymbol, identifierLoc);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002350}
2351
Olli Etuaho13389b62016-10-16 11:48:18 +01002352void TParseContext::parseDeclarator(TPublicType &publicType,
2353 const TSourceLoc &identifierLocation,
2354 const TString &identifier,
2355 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002356{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002357 // If the declaration starting this declarator list was empty (example: int,), some checks were
2358 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002359 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002360 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002361 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2362 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002363 }
2364
Olli Etuaho856c4972016-08-08 11:38:39 +03002365 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002366
Olli Etuaho856c4972016-08-08 11:38:39 +03002367 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002368
Olli Etuaho2935c582015-04-08 14:32:06 +03002369 TVariable *variable = nullptr;
Olli Etuaho43364892017-02-13 16:00:12 +00002370 TType type(publicType);
jchen104cdac9e2017-05-08 11:01:20 +08002371 if (IsAtomicCounter(publicType.getBasicType()))
2372 {
2373 checkAtomicCounterOffsetIsNotOverlapped(publicType, kAtomicCounterSize, true,
2374 identifierLocation, type);
2375 }
Olli Etuaho43364892017-02-13 16:00:12 +00002376 declareVariable(identifierLocation, identifier, type, &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002377
Olli Etuaho43364892017-02-13 16:00:12 +00002378 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002379 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002380 {
Jamie Madill502d66f2013-06-20 11:55:52 -04002381 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002382 declarationOut->appendDeclarator(symbol);
2383 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002384}
2385
Olli Etuaho13389b62016-10-16 11:48:18 +01002386void TParseContext::parseArrayDeclarator(TPublicType &publicType,
2387 const TSourceLoc &identifierLocation,
2388 const TString &identifier,
2389 const TSourceLoc &arrayLocation,
2390 TIntermTyped *indexExpression,
2391 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002392{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002393 // If the declaration starting this declarator list was empty (example: int,), some checks were
2394 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002395 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002396 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002397 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2398 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002399 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002400
Olli Etuaho856c4972016-08-08 11:38:39 +03002401 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002402
Olli Etuaho856c4972016-08-08 11:38:39 +03002403 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002404
Olli Etuaho8a176262016-08-16 14:23:01 +03002405 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04002406 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002407 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03002408 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03002409 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002410
jchen104cdac9e2017-05-08 11:01:20 +08002411 if (IsAtomicCounter(publicType.getBasicType()))
2412 {
2413 checkAtomicCounterOffsetIsNotOverlapped(publicType, kAtomicCounterArrayStride * size,
2414 true, identifierLocation, arrayType);
2415 }
2416
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002417 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002418 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04002419
Jamie Madillb98c3a82015-07-23 14:26:04 -04002420 TIntermSymbol *symbol =
2421 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002422 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002423 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002424
Olli Etuaho13389b62016-10-16 11:48:18 +01002425 declarationOut->appendDeclarator(symbol);
Jamie Madill502d66f2013-06-20 11:55:52 -04002426 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002427}
2428
Olli Etuaho13389b62016-10-16 11:48:18 +01002429void TParseContext::parseInitDeclarator(const TPublicType &publicType,
2430 const TSourceLoc &identifierLocation,
2431 const TString &identifier,
2432 const TSourceLoc &initLocation,
2433 TIntermTyped *initializer,
2434 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002435{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002436 // If the declaration starting this declarator list was empty (example: int,), some checks were
2437 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002438 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002439 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002440 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2441 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002442 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002443
Olli Etuaho856c4972016-08-08 11:38:39 +03002444 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002445
Olli Etuaho13389b62016-10-16 11:48:18 +01002446 TIntermBinary *initNode = nullptr;
Olli Etuaho914b79a2017-06-19 16:03:19 +03002447 if (executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04002448 {
2449 //
2450 // build the intermediate representation
2451 //
Olli Etuaho13389b62016-10-16 11:48:18 +01002452 if (initNode)
Jamie Madill502d66f2013-06-20 11:55:52 -04002453 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002454 declarationOut->appendDeclarator(initNode);
Jamie Madill502d66f2013-06-20 11:55:52 -04002455 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002456 }
2457}
2458
Olli Etuaho13389b62016-10-16 11:48:18 +01002459void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
2460 const TSourceLoc &identifierLocation,
2461 const TString &identifier,
2462 const TSourceLoc &indexLocation,
2463 TIntermTyped *indexExpression,
2464 const TSourceLoc &initLocation,
2465 TIntermTyped *initializer,
2466 TIntermDeclaration *declarationOut)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002467{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002468 // If the declaration starting this declarator list was empty (example: int,), some checks were
2469 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002470 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002471 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002472 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2473 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002474 }
2475
Olli Etuaho856c4972016-08-08 11:38:39 +03002476 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002477
Olli Etuaho8a176262016-08-16 14:23:01 +03002478 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002479
2480 TPublicType arrayType(publicType);
2481
Olli Etuaho856c4972016-08-08 11:38:39 +03002482 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002483 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2484 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002485 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002486 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002487 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002488 }
2489 // Make the type an array even if size check failed.
2490 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2491 arrayType.setArraySize(size);
2492
2493 // initNode will correspond to the whole of "b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002494 TIntermBinary *initNode = nullptr;
Olli Etuaho914b79a2017-06-19 16:03:19 +03002495 if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002496 {
2497 if (initNode)
2498 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002499 declarationOut->appendDeclarator(initNode);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002500 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002501 }
2502}
2503
jchen104cdac9e2017-05-08 11:01:20 +08002504void TParseContext::setAtomicCounterBindingDefaultOffset(const TPublicType &publicType,
2505 const TSourceLoc &location)
2506{
2507 const TLayoutQualifier &layoutQualifier = publicType.layoutQualifier;
2508 checkAtomicCounterBindingIsValid(location, layoutQualifier.binding);
2509 if (layoutQualifier.binding == -1 || layoutQualifier.offset == -1)
2510 {
2511 error(location, "Requires both binding and offset", "layout");
2512 return;
2513 }
2514 mAtomicCounterBindingStates[layoutQualifier.binding].setDefaultOffset(layoutQualifier.offset);
2515}
2516
Martin Radev70866b82016-07-22 15:27:42 +03002517void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
Jamie Madilla295edf2013-06-06 11:56:48 -04002518{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002519 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madilla295edf2013-06-06 11:56:48 -04002520 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04002521
Martin Radev70866b82016-07-22 15:27:42 +03002522 checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
2523 typeQualifier.line);
2524
Jamie Madillc2128ff2016-07-04 10:26:17 -04002525 // It should never be the case, but some strange parser errors can send us here.
2526 if (layoutQualifier.isEmpty())
2527 {
2528 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04002529 return;
2530 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002531
Martin Radev802abe02016-08-04 17:48:32 +03002532 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04002533 {
Olli Etuaho43364892017-02-13 16:00:12 +00002534 error(typeQualifier.line, "invalid layout qualifier combination", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04002535 return;
2536 }
2537
Olli Etuaho43364892017-02-13 16:00:12 +00002538 checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);
2539
2540 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev2cc85b32016-08-05 16:22:53 +03002541
2542 checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
2543
Andrei Volykhina5527072017-03-22 16:46:30 +03002544 checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv);
2545
jchen104cdac9e2017-05-08 11:01:20 +08002546 checkOffsetIsNotSpecified(typeQualifier.line, layoutQualifier.offset);
2547
Martin Radev802abe02016-08-04 17:48:32 +03002548 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04002549 {
Martin Radev802abe02016-08-04 17:48:32 +03002550 if (mComputeShaderLocalSizeDeclared &&
2551 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
2552 {
2553 error(typeQualifier.line, "Work group size does not match the previous declaration",
2554 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002555 return;
2556 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002557
Martin Radev802abe02016-08-04 17:48:32 +03002558 if (mShaderVersion < 310)
2559 {
2560 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002561 return;
2562 }
Jamie Madill099c0f32013-06-20 11:55:52 -04002563
Martin Radev4c4c8e72016-08-04 12:25:34 +03002564 if (!layoutQualifier.localSize.isAnyValueSet())
Martin Radev802abe02016-08-04 17:48:32 +03002565 {
2566 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002567 return;
2568 }
2569
2570 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
2571 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
2572
2573 const TConstantUnion *maxComputeWorkGroupSizeData =
2574 maxComputeWorkGroupSize->getConstPointer();
2575
2576 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
2577 {
2578 if (layoutQualifier.localSize[i] != -1)
2579 {
2580 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
2581 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
2582 if (mComputeShaderLocalSize[i] < 1 ||
2583 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
2584 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002585 std::stringstream reasonStream;
2586 reasonStream << "invalid value: Value must be at least 1 and no greater than "
2587 << maxComputeWorkGroupSizeValue;
2588 const std::string &reason = reasonStream.str();
Martin Radev802abe02016-08-04 17:48:32 +03002589
Olli Etuaho4de340a2016-12-16 09:32:03 +00002590 error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03002591 return;
2592 }
2593 }
2594 }
2595
2596 mComputeShaderLocalSizeDeclared = true;
2597 }
Olli Etuaho95468d12017-05-04 11:14:34 +03002598 else if (isMultiviewExtensionEnabled() && typeQualifier.qualifier == EvqVertexIn)
Olli Etuaho09b04a22016-12-15 13:30:26 +00002599 {
2600 // This error is only specified in WebGL, but tightens unspecified behavior in the native
2601 // specification.
2602 if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
2603 {
2604 error(typeQualifier.line, "Number of views does not match the previous declaration",
2605 "layout");
2606 return;
2607 }
2608
2609 if (layoutQualifier.numViews == -1)
2610 {
2611 error(typeQualifier.line, "No num_views specified", "layout");
2612 return;
2613 }
2614
2615 if (layoutQualifier.numViews > mMaxNumViews)
2616 {
2617 error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
2618 "layout");
2619 return;
2620 }
2621
2622 mNumViews = layoutQualifier.numViews;
2623 }
Martin Radev802abe02016-08-04 17:48:32 +03002624 else
Jamie Madill1566ef72013-06-20 11:55:54 -04002625 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00002626 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03002627 {
Martin Radev802abe02016-08-04 17:48:32 +03002628 return;
2629 }
2630
2631 if (typeQualifier.qualifier != EvqUniform)
2632 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002633 error(typeQualifier.line, "invalid qualifier: global layout must be uniform",
2634 getQualifierString(typeQualifier.qualifier));
Martin Radev802abe02016-08-04 17:48:32 +03002635 return;
2636 }
2637
2638 if (mShaderVersion < 300)
2639 {
2640 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
2641 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002642 return;
2643 }
2644
Olli Etuaho09b04a22016-12-15 13:30:26 +00002645 checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002646
2647 if (layoutQualifier.matrixPacking != EmpUnspecified)
2648 {
2649 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
2650 }
2651
2652 if (layoutQualifier.blockStorage != EbsUnspecified)
2653 {
2654 mDefaultBlockStorage = layoutQualifier.blockStorage;
2655 }
Jamie Madill1566ef72013-06-20 11:55:54 -04002656 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002657}
2658
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002659TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
2660 const TFunction &function,
2661 const TSourceLoc &location,
2662 bool insertParametersToSymbolTable)
2663{
Olli Etuahofe486322017-03-21 09:30:54 +00002664 TIntermFunctionPrototype *prototype =
2665 new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function));
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002666 // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
2667 // point to the data that already exists in the symbol table.
2668 prototype->getFunctionSymbolInfo()->setFromFunction(function);
2669 prototype->setLine(location);
2670
2671 for (size_t i = 0; i < function.getParamCount(); i++)
2672 {
2673 const TConstParameter &param = function.getParam(i);
2674
2675 // If the parameter has no name, it's not an error, just don't add it to symbol table (could
2676 // be used for unused args).
2677 if (param.name != nullptr)
2678 {
2679 TVariable *variable = new TVariable(param.name, *param.type);
2680
2681 // Insert the parameter in the symbol table.
2682 if (insertParametersToSymbolTable && !symbolTable.declare(variable))
2683 {
2684 error(location, "redefinition", variable->getName().c_str());
2685 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2686 continue;
2687 }
2688 TIntermSymbol *symbol = intermediate.addSymbol(
2689 variable->getUniqueId(), variable->getName(), variable->getType(), location);
2690 prototype->appendParameter(symbol);
2691 }
2692 else
2693 {
2694 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2695 }
2696 }
2697 return prototype;
2698}
2699
Olli Etuaho16c745a2017-01-16 17:02:27 +00002700TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
2701 const TFunction &parsedFunction,
2702 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002703{
Olli Etuaho476197f2016-10-11 13:59:08 +01002704 // Note: function found from the symbol table could be the same as parsedFunction if this is the
2705 // first declaration. Either way the instance in the symbol table is used to track whether the
2706 // function is declared multiple times.
2707 TFunction *function = static_cast<TFunction *>(
2708 symbolTable.find(parsedFunction.getMangledName(), getShaderVersion()));
2709 if (function->hasPrototypeDeclaration() && mShaderVersion == 100)
Olli Etuaho5d653182016-01-04 14:43:28 +02002710 {
2711 // ESSL 1.00.17 section 4.2.7.
2712 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
2713 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02002714 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002715 function->setHasPrototypeDeclaration();
Olli Etuaho5d653182016-01-04 14:43:28 +02002716
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002717 TIntermFunctionPrototype *prototype =
2718 createPrototypeNodeFromFunction(*function, location, false);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002719
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002720 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002721
2722 if (!symbolTable.atGlobalLevel())
2723 {
2724 // ESSL 3.00.4 section 4.2.4.
2725 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002726 }
2727
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002728 return prototype;
2729}
2730
Olli Etuaho336b1472016-10-05 16:37:55 +01002731TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002732 TIntermFunctionPrototype *functionPrototype,
Olli Etuaho336b1472016-10-05 16:37:55 +01002733 TIntermBlock *functionBody,
2734 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002735{
Olli Etuahof51fdd22016-10-03 10:03:40 +01002736 // Check that non-void functions have at least one return statement.
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002737 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2738 {
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002739 error(location, "function does not return a value:",
2740 functionPrototype->getFunctionSymbolInfo()->getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002741 }
2742
Olli Etuahof51fdd22016-10-03 10:03:40 +01002743 if (functionBody == nullptr)
2744 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01002745 functionBody = new TIntermBlock();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002746 functionBody->setLine(location);
2747 }
Olli Etuaho336b1472016-10-05 16:37:55 +01002748 TIntermFunctionDefinition *functionNode =
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002749 new TIntermFunctionDefinition(functionPrototype, functionBody);
Olli Etuaho336b1472016-10-05 16:37:55 +01002750 functionNode->setLine(location);
Olli Etuahof51fdd22016-10-03 10:03:40 +01002751
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002752 symbolTable.pop();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002753 return functionNode;
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002754}
2755
Olli Etuaho476197f2016-10-11 13:59:08 +01002756void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
2757 TFunction **function,
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002758 TIntermFunctionPrototype **prototypeOut)
Jamie Madill185fb402015-06-12 15:48:48 -04002759{
Olli Etuaho476197f2016-10-11 13:59:08 +01002760 ASSERT(function);
2761 ASSERT(*function);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002762 const TSymbol *builtIn =
Olli Etuaho476197f2016-10-11 13:59:08 +01002763 symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002764
2765 if (builtIn)
2766 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002767 error(location, "built-in functions cannot be redefined", (*function)->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002768 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002769 else
Jamie Madill185fb402015-06-12 15:48:48 -04002770 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002771 TFunction *prevDec = static_cast<TFunction *>(
2772 symbolTable.find((*function)->getMangledName(), getShaderVersion()));
2773
2774 // Note: 'prevDec' could be 'function' if this is the first time we've seen function as it
2775 // would have just been put in the symbol table. Otherwise, we're looking up an earlier
2776 // occurance.
2777 if (*function != prevDec)
2778 {
2779 // Swap the parameters of the previous declaration to the parameters of the function
2780 // definition (parameter names may differ).
2781 prevDec->swapParameters(**function);
2782
2783 // The function definition will share the same symbol as any previous declaration.
2784 *function = prevDec;
2785 }
2786
2787 if ((*function)->isDefined())
2788 {
2789 error(location, "function already has a body", (*function)->getName().c_str());
2790 }
2791
2792 (*function)->setDefined();
Jamie Madill185fb402015-06-12 15:48:48 -04002793 }
Jamie Madill185fb402015-06-12 15:48:48 -04002794
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002795 // Remember the return type for later checking for return statements.
Olli Etuaho476197f2016-10-11 13:59:08 +01002796 mCurrentFunctionType = &((*function)->getReturnType());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002797 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002798
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002799 *prototypeOut = createPrototypeNodeFromFunction(**function, location, true);
Jamie Madill185fb402015-06-12 15:48:48 -04002800 setLoopNestingLevel(0);
2801}
2802
Jamie Madillb98c3a82015-07-23 14:26:04 -04002803TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002804{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002805 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002806 // We don't know at this point whether this is a function definition or a prototype.
2807 // The definition production code will check for redefinitions.
2808 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002809 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002810 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2811 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002812 //
2813 TFunction *prevDec =
2814 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302815
Martin Radevda6254b2016-12-14 17:00:36 +02002816 if (getShaderVersion() >= 300 &&
2817 symbolTable.hasUnmangledBuiltInForShaderVersion(function->getName().c_str(),
2818 getShaderVersion()))
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302819 {
Martin Radevda6254b2016-12-14 17:00:36 +02002820 // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions.
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302821 // Therefore overloading or redefining builtin functions is an error.
2822 error(location, "Name of a built-in function cannot be redeclared as function",
2823 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302824 }
2825 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002826 {
2827 if (prevDec->getReturnType() != function->getReturnType())
2828 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002829 error(location, "function must have the same return type in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002830 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002831 }
2832 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2833 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002834 if (prevDec->getParam(i).type->getQualifier() !=
2835 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002836 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002837 error(location,
2838 "function must have the same parameter qualifiers in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002839 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002840 }
2841 }
2842 }
2843
2844 //
2845 // Check for previously declared variables using the same name.
2846 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002847 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002848 if (prevSym)
2849 {
2850 if (!prevSym->isFunction())
2851 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002852 error(location, "redefinition of a function", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002853 }
2854 }
2855 else
2856 {
2857 // Insert the unmangled name to detect potential future redefinition as a variable.
Olli Etuaho476197f2016-10-11 13:59:08 +01002858 symbolTable.getOuterLevel()->insertUnmangled(function);
Jamie Madill185fb402015-06-12 15:48:48 -04002859 }
2860
2861 // We're at the inner scope level of the function's arguments and body statement.
2862 // Add the function prototype to the surrounding scope instead.
2863 symbolTable.getOuterLevel()->insert(function);
2864
Olli Etuaho78d13742017-01-18 13:06:10 +00002865 // Raise error message if main function takes any parameters or return anything other than void
2866 if (function->getName() == "main")
2867 {
2868 if (function->getParamCount() > 0)
2869 {
2870 error(location, "function cannot take any parameter(s)", "main");
2871 }
2872 if (function->getReturnType().getBasicType() != EbtVoid)
2873 {
2874 error(location, "main function cannot return a value",
2875 function->getReturnType().getBasicString());
2876 }
2877 }
2878
Jamie Madill185fb402015-06-12 15:48:48 -04002879 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002880 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2881 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002882 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2883 //
2884 return function;
2885}
2886
Olli Etuaho9de84a52016-06-14 17:36:01 +03002887TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2888 const TString *name,
2889 const TSourceLoc &location)
2890{
2891 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2892 {
2893 error(location, "no qualifiers allowed for function return",
2894 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002895 }
2896 if (!type.layoutQualifier.isEmpty())
2897 {
2898 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002899 }
jchen10cc2a10e2017-05-03 14:05:12 +08002900 // make sure an opaque type is not involved as well...
2901 std::string reason(getBasicString(type.getBasicType()));
2902 reason += "s can't be function return values";
2903 checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002904 if (mShaderVersion < 300)
2905 {
2906 // Array return values are forbidden, but there's also no valid syntax for declaring array
2907 // return values in ESSL 1.00.
Olli Etuaho77ba4082016-12-16 12:01:18 +00002908 ASSERT(type.arraySize == 0 || mDiagnostics->numErrors() > 0);
Olli Etuahoe29324f2016-06-15 10:58:03 +03002909
2910 if (type.isStructureContainingArrays())
2911 {
2912 // ESSL 1.00.17 section 6.1 Function Definitions
2913 error(location, "structures containing arrays can't be function return values",
2914 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002915 }
2916 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002917
2918 // Add the function as a prototype after parsing it (we do not support recursion)
2919 return new TFunction(name, new TType(type));
2920}
2921
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002922TFunction *TParseContext::addConstructorFunc(const TPublicType &publicType)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002923{
Martin Radev4a9cd802016-09-01 16:51:51 +03002924 if (publicType.isStructSpecifier())
Olli Etuahobd163f62015-11-13 12:15:38 +02002925 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002926 error(publicType.getLine(), "constructor can't be a structure definition",
2927 getBasicString(publicType.getBasicType()));
Olli Etuahobd163f62015-11-13 12:15:38 +02002928 }
2929
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002930 TType *type = new TType(publicType);
2931 if (!type->canBeConstructed())
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002932 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002933 error(publicType.getLine(), "cannot construct this type",
2934 getBasicString(publicType.getBasicType()));
2935 type->setBasicType(EbtFloat);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002936 }
2937
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002938 return new TFunction(nullptr, type, EOpConstruct);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002939}
2940
Jamie Madillb98c3a82015-07-23 14:26:04 -04002941// This function is used to test for the correctness of the parameters passed to various constructor
2942// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002943//
Olli Etuaho856c4972016-08-08 11:38:39 +03002944// 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 +00002945//
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002946TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00002947 TType type,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302948 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002949{
Olli Etuaho856c4972016-08-08 11:38:39 +03002950 if (type.isUnsizedArray())
2951 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002952 if (arguments->empty())
Olli Etuahobbe9fb52016-11-03 17:16:05 +00002953 {
2954 error(line, "implicitly sized array constructor must have at least one argument", "[]");
2955 type.setArraySize(1u);
2956 return TIntermTyped::CreateZero(type);
2957 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002958 type.setArraySize(static_cast<unsigned int>(arguments->size()));
Olli Etuaho856c4972016-08-08 11:38:39 +03002959 }
Olli Etuaho856c4972016-08-08 11:38:39 +03002960
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002961 if (!checkConstructorArguments(line, arguments, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002962 {
Olli Etuaho72d10202017-01-19 15:58:30 +00002963 return TIntermTyped::CreateZero(type);
Olli Etuaho856c4972016-08-08 11:38:39 +03002964 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002965
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002966 TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002967 constructorNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002968
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002969 TIntermTyped *constConstructor =
2970 intermediate.foldAggregateBuiltIn(constructorNode, mDiagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002971 if (constConstructor)
2972 {
2973 return constConstructor;
2974 }
2975
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002976 return constructorNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002977}
2978
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002979//
2980// Interface/uniform blocks
2981//
Olli Etuaho13389b62016-10-16 11:48:18 +01002982TIntermDeclaration *TParseContext::addInterfaceBlock(
Martin Radev70866b82016-07-22 15:27:42 +03002983 const TTypeQualifierBuilder &typeQualifierBuilder,
2984 const TSourceLoc &nameLine,
2985 const TString &blockName,
2986 TFieldList *fieldList,
2987 const TString *instanceName,
2988 const TSourceLoc &instanceLine,
2989 TIntermTyped *arrayIndex,
2990 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002991{
Olli Etuaho856c4972016-08-08 11:38:39 +03002992 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002993
Olli Etuaho77ba4082016-12-16 12:01:18 +00002994 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03002995
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002996 if (typeQualifier.qualifier != EvqUniform)
2997 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002998 error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform",
2999 getQualifierString(typeQualifier.qualifier));
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003000 }
3001
Martin Radev70866b82016-07-22 15:27:42 +03003002 if (typeQualifier.invariant)
3003 {
3004 error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
3005 }
3006
Olli Etuaho43364892017-02-13 16:00:12 +00003007 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
3008
jchen10af713a22017-04-19 09:10:56 +08003009 // add array index
3010 unsigned int arraySize = 0;
3011 if (arrayIndex != nullptr)
3012 {
3013 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
3014 }
3015
3016 if (mShaderVersion < 310)
3017 {
3018 checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
3019 }
3020 else
3021 {
3022 checkBlockBindingIsValid(typeQualifier.line, typeQualifier.layoutQualifier.binding,
3023 arraySize);
3024 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003025
Andrei Volykhina5527072017-03-22 16:46:30 +03003026 checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
3027
Jamie Madill099c0f32013-06-20 11:55:52 -04003028 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03003029 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003030
Jamie Madill099c0f32013-06-20 11:55:52 -04003031 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
3032 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003033 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04003034 }
3035
Jamie Madill1566ef72013-06-20 11:55:54 -04003036 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
3037 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003038 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04003039 }
3040
Olli Etuaho856c4972016-08-08 11:38:39 +03003041 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003042
Martin Radev2cc85b32016-08-05 16:22:53 +03003043 checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
3044
Arun Patole7e7e68d2015-05-22 12:02:25 +05303045 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
3046 if (!symbolTable.declare(blockNameSymbol))
3047 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003048 error(nameLine, "redefinition of an interface block name", blockName.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003049 }
3050
Jamie Madill98493dd2013-07-08 14:39:03 -04003051 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05303052 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
3053 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003054 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05303055 TType *fieldType = field->type();
jchen10cc2a10e2017-05-03 14:05:12 +08003056 if (IsOpaqueType(fieldType->getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +05303057 {
jchen10cc2a10e2017-05-03 14:05:12 +08003058 std::string reason("unsupported type - ");
3059 reason += fieldType->getBasicString();
3060 reason += " types are not allowed in interface blocks";
3061 error(field->line(), reason.c_str(), fieldType->getBasicString());
Martin Radev2cc85b32016-08-05 16:22:53 +03003062 }
3063
Jamie Madill98493dd2013-07-08 14:39:03 -04003064 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003065 switch (qualifier)
3066 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003067 case EvqGlobal:
3068 case EvqUniform:
3069 break;
3070 default:
3071 error(field->line(), "invalid qualifier on interface block member",
3072 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003073 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003074 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003075
Martin Radev70866b82016-07-22 15:27:42 +03003076 if (fieldType->isInvariant())
3077 {
3078 error(field->line(), "invalid qualifier on interface block member", "invariant");
3079 }
3080
Jamie Madilla5efff92013-06-06 11:56:47 -04003081 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04003082 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03003083 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
jchen10af713a22017-04-19 09:10:56 +08003084 checkBindingIsNotSpecified(field->line(), fieldLayoutQualifier.binding);
Jamie Madill099c0f32013-06-20 11:55:52 -04003085
Jamie Madill98493dd2013-07-08 14:39:03 -04003086 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04003087 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003088 error(field->line(), "invalid layout qualifier: cannot be used here",
3089 getBlockStorageString(fieldLayoutQualifier.blockStorage));
Jamie Madill1566ef72013-06-20 11:55:54 -04003090 }
3091
Jamie Madill98493dd2013-07-08 14:39:03 -04003092 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04003093 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003094 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04003095 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03003096 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04003097 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003098 warning(field->line(),
3099 "extraneous layout qualifier: only has an effect on matrix types",
3100 getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
Jamie Madill099c0f32013-06-20 11:55:52 -04003101 }
3102
Jamie Madill98493dd2013-07-08 14:39:03 -04003103 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003104 }
3105
Jamie Madillb98c3a82015-07-23 14:26:04 -04003106 TInterfaceBlock *interfaceBlock =
3107 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
3108 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
3109 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003110
3111 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04003112 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003113
Jamie Madill98493dd2013-07-08 14:39:03 -04003114 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003115 {
3116 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04003117 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
3118 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003119 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05303120 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04003121
3122 // set parent pointer of the field variable
3123 fieldType->setInterfaceBlock(interfaceBlock);
3124
Arun Patole7e7e68d2015-05-22 12:02:25 +05303125 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04003126 fieldVariable->setQualifier(typeQualifier.qualifier);
3127
Arun Patole7e7e68d2015-05-22 12:02:25 +05303128 if (!symbolTable.declare(fieldVariable))
3129 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003130 error(field->line(), "redefinition of an interface block member name",
3131 field->name().c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003132 }
3133 }
3134 }
3135 else
3136 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003137 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03003138
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003139 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05303140 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003141 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04003142
Arun Patole7e7e68d2015-05-22 12:02:25 +05303143 if (!symbolTable.declare(instanceTypeDef))
3144 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003145 error(instanceLine, "redefinition of an interface block instance name",
3146 instanceName->c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003147 }
3148
Jamie Madillb98c3a82015-07-23 14:26:04 -04003149 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003150 symbolName = instanceTypeDef->getName();
3151 }
3152
Olli Etuaho13389b62016-10-16 11:48:18 +01003153 TIntermSymbol *blockSymbol =
3154 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line);
3155 TIntermDeclaration *declaration = new TIntermDeclaration();
3156 declaration->appendDeclarator(blockSymbol);
3157 declaration->setLine(nameLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04003158
3159 exitStructDeclaration();
Olli Etuaho13389b62016-10-16 11:48:18 +01003160 return declaration;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003161}
3162
Olli Etuaho383b7912016-08-05 11:22:59 +03003163void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00003164{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003165 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003166
3167 // Embedded structure definitions are not supported per GLSL ES spec.
Olli Etuaho4de340a2016-12-16 09:32:03 +00003168 // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
Arun Patole7e7e68d2015-05-22 12:02:25 +05303169 if (mStructNestingLevel > 1)
3170 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003171 error(line, "Embedded struct definitions are not allowed", "struct");
kbr@chromium.org476541f2011-10-27 21:14:51 +00003172 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00003173}
3174
3175void TParseContext::exitStructDeclaration()
3176{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003177 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003178}
3179
Olli Etuaho8a176262016-08-16 14:23:01 +03003180void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00003181{
Jamie Madillacb4b812016-11-07 13:50:29 -05003182 if (!sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +05303183 {
Olli Etuaho8a176262016-08-16 14:23:01 +03003184 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003185 }
3186
Arun Patole7e7e68d2015-05-22 12:02:25 +05303187 if (field.type()->getBasicType() != EbtStruct)
3188 {
Olli Etuaho8a176262016-08-16 14:23:01 +03003189 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003190 }
3191
3192 // We're already inside a structure definition at this point, so add
3193 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05303194 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
3195 {
Jamie Madill41a49272014-03-18 16:10:13 -04003196 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003197 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
3198 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04003199 std::string reason = reasonStream.str();
Olli Etuaho4de340a2016-12-16 09:32:03 +00003200 error(line, reason.c_str(), field.name().c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03003201 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003202 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00003203}
3204
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003205//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003206// Parse an array index expression
3207//
Jamie Madillb98c3a82015-07-23 14:26:04 -04003208TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
3209 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303210 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003211{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003212 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
3213 {
3214 if (baseExpression->getAsSymbolNode())
3215 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303216 error(location, " left of '[' is not of type array, matrix, or vector ",
3217 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003218 }
3219 else
3220 {
3221 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
3222 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003223
3224 TConstantUnion *unionArray = new TConstantUnion[1];
3225 unionArray->setFConst(0.0f);
3226 return intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst),
3227 location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003228 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003229
Jamie Madill21c1e452014-12-29 11:33:41 -05003230 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
3231
Olli Etuaho36b05142015-11-12 13:10:42 +02003232 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
3233 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
3234 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
3235 // index is a constant expression.
3236 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
3237 {
3238 if (baseExpression->isInterfaceBlock())
3239 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003240 error(location,
3241 "array indexes for interface blocks arrays must be constant integral expressions",
3242 "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02003243 }
3244 else if (baseExpression->getQualifier() == EvqFragmentOut)
3245 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003246 error(location,
3247 "array indexes for fragment outputs must be constant integral expressions", "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02003248 }
Olli Etuaho3e960462015-11-12 15:58:39 +02003249 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
3250 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003251 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3e960462015-11-12 15:58:39 +02003252 }
Olli Etuaho36b05142015-11-12 13:10:42 +02003253 }
3254
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003255 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04003256 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003257 // If an out-of-range index is not qualified as constant, the behavior in the spec is
3258 // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
3259 // constant fold expressions that are not constant expressions). The most compatible way to
3260 // handle this case is to report a warning instead of an error and force the index to be in
3261 // the correct range.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003262 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003263 int index = indexConstantUnion->getIConst(0);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003264
3265 int safeIndex = -1;
3266
3267 if (baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04003268 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003269 if (baseExpression->getQualifier() == EvqFragData && index > 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003270 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003271 if (mShaderSpec == SH_WEBGL2_SPEC)
3272 {
3273 // Error has been already generated if index is not const.
3274 if (indexExpression->getQualifier() == EvqConst)
3275 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003276 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003277 }
3278 safeIndex = 0;
3279 }
3280 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
3281 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003282 outOfRangeError(outOfRangeIndexIsError, location,
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003283 "array index for gl_FragData must be zero when "
Olli Etuaho4de340a2016-12-16 09:32:03 +00003284 "GL_EXT_draw_buffers is disabled",
3285 "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003286 safeIndex = 0;
3287 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03003288 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003289 // Only do generic out-of-range check if similar error hasn't already been reported.
3290 if (safeIndex < 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003291 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003292 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3293 baseExpression->getArraySize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003294 "array index out of range");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003295 }
3296 }
3297 else if (baseExpression->isMatrix())
3298 {
3299 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
Olli Etuaho90892fb2016-07-14 14:44:51 +03003300 baseExpression->getType().getCols(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003301 "matrix field selection out of range");
Jamie Madill7164cf42013-07-08 13:30:59 -04003302 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003303 else if (baseExpression->isVector())
Jamie Madill7164cf42013-07-08 13:30:59 -04003304 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003305 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3306 baseExpression->getType().getNominalSize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003307 "vector field selection out of range");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003308 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003309
3310 ASSERT(safeIndex >= 0);
3311 // Data of constant unions can't be changed, because it may be shared with other
3312 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
3313 // sanitized object.
3314 if (safeIndex != index)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003315 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003316 TConstantUnion *safeConstantUnion = new TConstantUnion();
3317 safeConstantUnion->setIConst(safeIndex);
3318 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003319 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003320
3321 return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003322 mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003323 }
Jamie Madill7164cf42013-07-08 13:30:59 -04003324 else
3325 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003326 return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003327 mDiagnostics);
Jamie Madill7164cf42013-07-08 13:30:59 -04003328 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003329}
3330
Olli Etuaho90892fb2016-07-14 14:44:51 +03003331int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
3332 const TSourceLoc &location,
3333 int index,
3334 int arraySize,
Olli Etuaho4de340a2016-12-16 09:32:03 +00003335 const char *reason)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003336{
3337 if (index >= arraySize || index < 0)
3338 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003339 std::stringstream reasonStream;
3340 reasonStream << reason << " '" << index << "'";
3341 std::string token = reasonStream.str();
3342 outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
Olli Etuaho90892fb2016-07-14 14:44:51 +03003343 if (index < 0)
3344 {
3345 return 0;
3346 }
3347 else
3348 {
3349 return arraySize - 1;
3350 }
3351 }
3352 return index;
3353}
3354
Jamie Madillb98c3a82015-07-23 14:26:04 -04003355TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
3356 const TSourceLoc &dotLocation,
3357 const TString &fieldString,
3358 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003359{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003360 if (baseExpression->isArray())
3361 {
3362 error(fieldLocation, "cannot apply dot operator to an array", ".");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003363 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003364 }
3365
3366 if (baseExpression->isVector())
3367 {
3368 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003369 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
3370 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003371 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003372 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003373 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003374 }
3375
Olli Etuahob6fa0432016-09-28 16:28:05 +01003376 return TIntermediate::AddSwizzle(baseExpression, fields, dotLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003377 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003378 else if (baseExpression->getBasicType() == EbtStruct)
3379 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303380 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003381 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003382 {
3383 error(dotLocation, "structure has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003384 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003385 }
3386 else
3387 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003388 bool fieldFound = false;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003389 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003390 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003391 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003392 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003393 {
3394 fieldFound = true;
3395 break;
3396 }
3397 }
3398 if (fieldFound)
3399 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003400 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3401 index->setLine(fieldLocation);
3402 return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003403 dotLocation, mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003404 }
3405 else
3406 {
3407 error(dotLocation, " no such field in structure", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003408 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003409 }
3410 }
3411 }
Jamie Madill98493dd2013-07-08 14:39:03 -04003412 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003413 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303414 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003415 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003416 {
3417 error(dotLocation, "interface block has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003418 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003419 }
3420 else
3421 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003422 bool fieldFound = false;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003423 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003424 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003425 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003426 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003427 {
3428 fieldFound = true;
3429 break;
3430 }
3431 }
3432 if (fieldFound)
3433 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003434 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3435 index->setLine(fieldLocation);
3436 return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003437 dotLocation, mDiagnostics);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003438 }
3439 else
3440 {
3441 error(dotLocation, " no such field in interface block", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003442 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003443 }
3444 }
3445 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003446 else
3447 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003448 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003449 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03003450 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303451 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003452 }
3453 else
3454 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303455 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03003456 " field selection requires structure, vector, or interface block on left hand "
3457 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303458 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003459 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003460 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003461 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003462}
3463
Jamie Madillb98c3a82015-07-23 14:26:04 -04003464TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3465 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003466{
Martin Radev802abe02016-08-04 17:48:32 +03003467 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003468
3469 if (qualifierType == "shared")
3470 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003471 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003472 {
3473 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
3474 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003475 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003476 }
3477 else if (qualifierType == "packed")
3478 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003479 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003480 {
3481 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
3482 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003483 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003484 }
3485 else if (qualifierType == "std140")
3486 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003487 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003488 }
3489 else if (qualifierType == "row_major")
3490 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003491 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003492 }
3493 else if (qualifierType == "column_major")
3494 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003495 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003496 }
3497 else if (qualifierType == "location")
3498 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003499 error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
3500 qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003501 }
Andrei Volykhina5527072017-03-22 16:46:30 +03003502 else if (qualifierType == "yuv" && isExtensionEnabled("GL_EXT_YUV_target") &&
3503 mShaderType == GL_FRAGMENT_SHADER)
3504 {
3505 qualifier.yuv = true;
3506 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003507 else if (qualifierType == "rgba32f")
3508 {
3509 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3510 qualifier.imageInternalFormat = EiifRGBA32F;
3511 }
3512 else if (qualifierType == "rgba16f")
3513 {
3514 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3515 qualifier.imageInternalFormat = EiifRGBA16F;
3516 }
3517 else if (qualifierType == "r32f")
3518 {
3519 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3520 qualifier.imageInternalFormat = EiifR32F;
3521 }
3522 else if (qualifierType == "rgba8")
3523 {
3524 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3525 qualifier.imageInternalFormat = EiifRGBA8;
3526 }
3527 else if (qualifierType == "rgba8_snorm")
3528 {
3529 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3530 qualifier.imageInternalFormat = EiifRGBA8_SNORM;
3531 }
3532 else if (qualifierType == "rgba32i")
3533 {
3534 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3535 qualifier.imageInternalFormat = EiifRGBA32I;
3536 }
3537 else if (qualifierType == "rgba16i")
3538 {
3539 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3540 qualifier.imageInternalFormat = EiifRGBA16I;
3541 }
3542 else if (qualifierType == "rgba8i")
3543 {
3544 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3545 qualifier.imageInternalFormat = EiifRGBA8I;
3546 }
3547 else if (qualifierType == "r32i")
3548 {
3549 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3550 qualifier.imageInternalFormat = EiifR32I;
3551 }
3552 else if (qualifierType == "rgba32ui")
3553 {
3554 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3555 qualifier.imageInternalFormat = EiifRGBA32UI;
3556 }
3557 else if (qualifierType == "rgba16ui")
3558 {
3559 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3560 qualifier.imageInternalFormat = EiifRGBA16UI;
3561 }
3562 else if (qualifierType == "rgba8ui")
3563 {
3564 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3565 qualifier.imageInternalFormat = EiifRGBA8UI;
3566 }
3567 else if (qualifierType == "r32ui")
3568 {
3569 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3570 qualifier.imageInternalFormat = EiifR32UI;
3571 }
3572
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003573 else
3574 {
3575 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003576 }
3577
Jamie Madilla5efff92013-06-06 11:56:47 -04003578 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003579}
3580
Martin Radev802abe02016-08-04 17:48:32 +03003581void TParseContext::parseLocalSize(const TString &qualifierType,
3582 const TSourceLoc &qualifierTypeLine,
3583 int intValue,
3584 const TSourceLoc &intValueLine,
3585 const std::string &intValueString,
3586 size_t index,
Martin Radev4c4c8e72016-08-04 12:25:34 +03003587 sh::WorkGroupSize *localSize)
Martin Radev802abe02016-08-04 17:48:32 +03003588{
Olli Etuaho856c4972016-08-08 11:38:39 +03003589 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03003590 if (intValue < 1)
3591 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003592 std::stringstream reasonStream;
3593 reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
3594 std::string reason = reasonStream.str();
3595 error(intValueLine, reason.c_str(), intValueString.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003596 }
3597 (*localSize)[index] = intValue;
3598}
3599
Olli Etuaho09b04a22016-12-15 13:30:26 +00003600void TParseContext::parseNumViews(int intValue,
3601 const TSourceLoc &intValueLine,
3602 const std::string &intValueString,
3603 int *numViews)
3604{
3605 // This error is only specified in WebGL, but tightens unspecified behavior in the native
3606 // specification.
3607 if (intValue < 1)
3608 {
3609 error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
3610 }
3611 *numViews = intValue;
3612}
3613
Jamie Madillb98c3a82015-07-23 14:26:04 -04003614TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3615 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003616 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303617 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003618{
Martin Radev802abe02016-08-04 17:48:32 +03003619 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003620
Martin Radev802abe02016-08-04 17:48:32 +03003621 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003622
Martin Radev802abe02016-08-04 17:48:32 +03003623 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003624 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003625 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003626 if (intValue < 0)
3627 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003628 error(intValueLine, "out of range: location must be non-negative",
3629 intValueString.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003630 }
3631 else
3632 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003633 qualifier.location = intValue;
Olli Etuaho87d410c2016-09-05 13:33:26 +03003634 qualifier.locationsSpecified = 1;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003635 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003636 }
Olli Etuaho43364892017-02-13 16:00:12 +00003637 else if (qualifierType == "binding")
3638 {
3639 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3640 if (intValue < 0)
3641 {
3642 error(intValueLine, "out of range: binding must be non-negative",
3643 intValueString.c_str());
3644 }
3645 else
3646 {
3647 qualifier.binding = intValue;
3648 }
3649 }
jchen104cdac9e2017-05-08 11:01:20 +08003650 else if (qualifierType == "offset")
3651 {
3652 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3653 if (intValue < 0)
3654 {
3655 error(intValueLine, "out of range: offset must be non-negative",
3656 intValueString.c_str());
3657 }
3658 else
3659 {
3660 qualifier.offset = intValue;
3661 }
3662 }
Martin Radev802abe02016-08-04 17:48:32 +03003663 else if (qualifierType == "local_size_x")
3664 {
3665 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3666 &qualifier.localSize);
3667 }
3668 else if (qualifierType == "local_size_y")
3669 {
3670 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3671 &qualifier.localSize);
3672 }
3673 else if (qualifierType == "local_size_z")
3674 {
3675 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3676 &qualifier.localSize);
3677 }
Olli Etuaho95468d12017-05-04 11:14:34 +03003678 else if (qualifierType == "num_views" && isMultiviewExtensionEnabled() &&
Olli Etuaho09b04a22016-12-15 13:30:26 +00003679 mShaderType == GL_VERTEX_SHADER)
3680 {
3681 parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
3682 }
Martin Radev802abe02016-08-04 17:48:32 +03003683 else
3684 {
3685 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003686 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003687
Jamie Madilla5efff92013-06-06 11:56:47 -04003688 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003689}
3690
Olli Etuaho613b9592016-09-05 12:05:53 +03003691TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
3692{
3693 return new TTypeQualifierBuilder(
3694 new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
3695 mShaderVersion);
3696}
3697
Jamie Madillb98c3a82015-07-23 14:26:04 -04003698TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003699 TLayoutQualifier rightQualifier,
3700 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003701{
Martin Radevc28888b2016-07-22 15:27:42 +03003702 return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003703 mDiagnostics);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003704}
3705
Olli Etuaho4de340a2016-12-16 09:32:03 +00003706TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
3707 const TFieldList *newlyAddedFields,
3708 const TSourceLoc &location)
3709{
3710 for (TField *field : *newlyAddedFields)
3711 {
3712 for (TField *oldField : *processedFields)
3713 {
3714 if (oldField->name() == field->name())
3715 {
3716 error(location, "duplicate field name in structure", field->name().c_str());
3717 }
3718 }
3719 processedFields->push_back(field);
3720 }
3721 return processedFields;
3722}
3723
Martin Radev70866b82016-07-22 15:27:42 +03003724TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
3725 const TTypeQualifierBuilder &typeQualifierBuilder,
3726 TPublicType *typeSpecifier,
3727 TFieldList *fieldList)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003728{
Olli Etuaho77ba4082016-12-16 12:01:18 +00003729 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003730
Martin Radev70866b82016-07-22 15:27:42 +03003731 typeSpecifier->qualifier = typeQualifier.qualifier;
3732 typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03003733 typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03003734 typeSpecifier->invariant = typeQualifier.invariant;
3735 if (typeQualifier.precision != EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +05303736 {
Martin Radev70866b82016-07-22 15:27:42 +03003737 typeSpecifier->precision = typeQualifier.precision;
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003738 }
Martin Radev70866b82016-07-22 15:27:42 +03003739 return addStructDeclaratorList(*typeSpecifier, fieldList);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003740}
3741
Jamie Madillb98c3a82015-07-23 14:26:04 -04003742TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3743 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003744{
Martin Radev4a9cd802016-09-01 16:51:51 +03003745 checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
3746 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03003747
Martin Radev4a9cd802016-09-01 16:51:51 +03003748 checkIsNonVoid(typeSpecifier.getLine(), (*fieldList)[0]->name(), typeSpecifier.getBasicType());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003749
Martin Radev4a9cd802016-09-01 16:51:51 +03003750 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003751
Arun Patole7e7e68d2015-05-22 12:02:25 +05303752 for (unsigned int i = 0; i < fieldList->size(); ++i)
3753 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003754 //
3755 // Careful not to replace already known aspects of type, like array-ness
3756 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303757 TType *type = (*fieldList)[i]->type();
Martin Radev4a9cd802016-09-01 16:51:51 +03003758 type->setBasicType(typeSpecifier.getBasicType());
3759 type->setPrimarySize(typeSpecifier.getPrimarySize());
3760 type->setSecondarySize(typeSpecifier.getSecondarySize());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003761 type->setPrecision(typeSpecifier.precision);
3762 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003763 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
Martin Radev2cc85b32016-08-05 16:22:53 +03003764 type->setMemoryQualifier(typeSpecifier.memoryQualifier);
Martin Radev70866b82016-07-22 15:27:42 +03003765 type->setInvariant(typeSpecifier.invariant);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003766
3767 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303768 if (type->isArray())
3769 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003770 checkIsValidTypeForArray(typeSpecifier.getLine(), typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003771 }
3772 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003773 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Martin Radev4a9cd802016-09-01 16:51:51 +03003774 if (typeSpecifier.getUserDef())
Arun Patole7e7e68d2015-05-22 12:02:25 +05303775 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003776 type->setStruct(typeSpecifier.getUserDef()->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003777 }
3778
Martin Radev4a9cd802016-09-01 16:51:51 +03003779 checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003780 }
3781
Jamie Madill98493dd2013-07-08 14:39:03 -04003782 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003783}
3784
Martin Radev4a9cd802016-09-01 16:51:51 +03003785TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
3786 const TSourceLoc &nameLine,
3787 const TString *structName,
3788 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003789{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303790 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003791 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003792
Jamie Madill9b820842015-02-12 10:40:10 -05003793 // Store a bool in the struct if we're at global scope, to allow us to
3794 // skip the local struct scoping workaround in HLSL.
Jamie Madill9b820842015-02-12 10:40:10 -05003795 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003796
Jamie Madill98493dd2013-07-08 14:39:03 -04003797 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003798 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003799 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303800 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3801 if (!symbolTable.declare(userTypeDef))
3802 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003803 error(nameLine, "redefinition of a struct", structName->c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003804 }
3805 }
3806
3807 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003808 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003809 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003810 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003811 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003812 switch (qualifier)
3813 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003814 case EvqGlobal:
3815 case EvqTemporary:
3816 break;
3817 default:
3818 error(field.line(), "invalid qualifier on struct member",
3819 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003820 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003821 }
Martin Radev70866b82016-07-22 15:27:42 +03003822 if (field.type()->isInvariant())
3823 {
3824 error(field.line(), "invalid qualifier on struct member", "invariant");
3825 }
jchen104cdac9e2017-05-08 11:01:20 +08003826 // ESSL 3.10 section 4.1.8 -- atomic_uint or images are not allowed as structure member.
3827 if (IsImage(field.type()->getBasicType()) || IsAtomicCounter(field.type()->getBasicType()))
Martin Radev2cc85b32016-08-05 16:22:53 +03003828 {
3829 error(field.line(), "disallowed type in struct", field.type()->getBasicString());
3830 }
3831
Olli Etuaho43364892017-02-13 16:00:12 +00003832 checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
3833
3834 checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);
Martin Radev70866b82016-07-22 15:27:42 +03003835
3836 checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003837 }
3838
Martin Radev4a9cd802016-09-01 16:51:51 +03003839 TTypeSpecifierNonArray typeSpecifierNonArray;
3840 typeSpecifierNonArray.initialize(EbtStruct, structLine);
3841 typeSpecifierNonArray.userDef = structureType;
3842 typeSpecifierNonArray.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003843 exitStructDeclaration();
3844
Martin Radev4a9cd802016-09-01 16:51:51 +03003845 return typeSpecifierNonArray;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003846}
3847
Jamie Madillb98c3a82015-07-23 14:26:04 -04003848TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01003849 TIntermBlock *statementList,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003850 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003851{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003852 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003853 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003854 init->isVector())
3855 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003856 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3857 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003858 return nullptr;
3859 }
3860
Olli Etuahoac5274d2015-02-20 10:19:08 +02003861 if (statementList)
3862 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00003863 if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
Olli Etuahoac5274d2015-02-20 10:19:08 +02003864 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003865 return nullptr;
3866 }
3867 }
3868
Olli Etuahoa3a36662015-02-17 13:46:51 +02003869 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3870 if (node == nullptr)
3871 {
3872 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003873 return nullptr;
3874 }
3875 return node;
3876}
3877
3878TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3879{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003880 if (mSwitchNestingLevel == 0)
3881 {
3882 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003883 return nullptr;
3884 }
3885 if (condition == nullptr)
3886 {
3887 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003888 return nullptr;
3889 }
3890 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003891 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003892 {
3893 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003894 }
3895 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003896 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3897 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3898 // fold in case labels.
3899 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003900 {
3901 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003902 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003903 TIntermCase *node = intermediate.addCase(condition, loc);
3904 if (node == nullptr)
3905 {
3906 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003907 return nullptr;
3908 }
3909 return node;
3910}
3911
3912TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3913{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003914 if (mSwitchNestingLevel == 0)
3915 {
3916 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003917 return nullptr;
3918 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003919 TIntermCase *node = intermediate.addCase(nullptr, loc);
3920 if (node == nullptr)
3921 {
3922 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003923 return nullptr;
3924 }
3925 return node;
3926}
3927
Jamie Madillb98c3a82015-07-23 14:26:04 -04003928TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3929 TIntermTyped *child,
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003930 const TSourceLoc &loc)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003931{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003932 ASSERT(child != nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003933
3934 switch (op)
3935 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003936 case EOpLogicalNot:
3937 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3938 child->isVector())
3939 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003940 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003941 return nullptr;
3942 }
3943 break;
3944 case EOpBitwiseNot:
3945 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3946 child->isMatrix() || child->isArray())
3947 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003948 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003949 return nullptr;
3950 }
3951 break;
3952 case EOpPostIncrement:
3953 case EOpPreIncrement:
3954 case EOpPostDecrement:
3955 case EOpPreDecrement:
3956 case EOpNegative:
3957 case EOpPositive:
Olli Etuaho94050052017-05-08 14:17:44 +03003958 if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() ||
3959 child->getBasicType() == EbtBool || child->isArray() ||
3960 IsOpaqueType(child->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -04003961 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003962 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003963 return nullptr;
3964 }
3965 // Operators for built-ins are already type checked against their prototype.
3966 default:
3967 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003968 }
3969
Olli Etuahof119a262016-08-19 15:54:22 +03003970 TIntermUnary *node = new TIntermUnary(op, child);
3971 node->setLine(loc);
Olli Etuahof119a262016-08-19 15:54:22 +03003972
Olli Etuaho77ba4082016-12-16 12:01:18 +00003973 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuahof119a262016-08-19 15:54:22 +03003974 if (foldedNode)
3975 return foldedNode;
3976
3977 return node;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003978}
3979
Olli Etuaho09b22472015-02-11 11:47:26 +02003980TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3981{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003982 TIntermTyped *node = createUnaryMath(op, child, loc);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003983 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003984 {
Olli Etuaho09b22472015-02-11 11:47:26 +02003985 return child;
3986 }
3987 return node;
3988}
3989
Jamie Madillb98c3a82015-07-23 14:26:04 -04003990TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3991 TIntermTyped *child,
3992 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003993{
Olli Etuaho856c4972016-08-08 11:38:39 +03003994 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003995 return addUnaryMath(op, child, loc);
3996}
3997
Jamie Madillb98c3a82015-07-23 14:26:04 -04003998bool TParseContext::binaryOpCommonCheck(TOperator op,
3999 TIntermTyped *left,
4000 TIntermTyped *right,
4001 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004002{
jchen10b4cf5652017-05-05 18:51:17 +08004003 // Check opaque types are not allowed to be operands in expressions other than array indexing
4004 // and structure member selection.
4005 if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType()))
4006 {
4007 switch (op)
4008 {
4009 case EOpIndexDirect:
4010 case EOpIndexIndirect:
4011 break;
4012 case EOpIndexDirectStruct:
4013 UNREACHABLE();
4014
4015 default:
4016 error(loc, "Invalid operation for variables with an opaque type",
4017 GetOperatorString(op));
4018 return false;
4019 }
4020 }
jchen10cc2a10e2017-05-03 14:05:12 +08004021
Olli Etuaho244be012016-08-18 15:26:02 +03004022 if (left->getType().getStruct() || right->getType().getStruct())
4023 {
4024 switch (op)
4025 {
4026 case EOpIndexDirectStruct:
4027 ASSERT(left->getType().getStruct());
4028 break;
4029 case EOpEqual:
4030 case EOpNotEqual:
4031 case EOpAssign:
4032 case EOpInitialize:
4033 if (left->getType() != right->getType())
4034 {
4035 return false;
4036 }
4037 break;
4038 default:
4039 error(loc, "Invalid operation for structs", GetOperatorString(op));
4040 return false;
4041 }
4042 }
4043
Olli Etuaho94050052017-05-08 14:17:44 +03004044 if (left->isInterfaceBlock() || right->isInterfaceBlock())
4045 {
4046 switch (op)
4047 {
4048 case EOpIndexDirectInterfaceBlock:
4049 ASSERT(left->getType().getInterfaceBlock());
4050 break;
4051 default:
4052 error(loc, "Invalid operation for interface blocks", GetOperatorString(op));
4053 return false;
4054 }
4055 }
4056
Olli Etuahod6b14282015-03-17 14:31:35 +02004057 if (left->isArray() || right->isArray())
4058 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004059 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02004060 {
4061 error(loc, "Invalid operation for arrays", GetOperatorString(op));
4062 return false;
4063 }
4064
4065 if (left->isArray() != right->isArray())
4066 {
4067 error(loc, "array / non-array mismatch", GetOperatorString(op));
4068 return false;
4069 }
4070
4071 switch (op)
4072 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004073 case EOpEqual:
4074 case EOpNotEqual:
4075 case EOpAssign:
4076 case EOpInitialize:
4077 break;
4078 default:
4079 error(loc, "Invalid operation for arrays", GetOperatorString(op));
4080 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02004081 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03004082 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02004083 if (left->getArraySize() != right->getArraySize())
4084 {
4085 error(loc, "array size mismatch", GetOperatorString(op));
4086 return false;
4087 }
Olli Etuahod6b14282015-03-17 14:31:35 +02004088 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004089
4090 // Check ops which require integer / ivec parameters
4091 bool isBitShift = false;
4092 switch (op)
4093 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004094 case EOpBitShiftLeft:
4095 case EOpBitShiftRight:
4096 case EOpBitShiftLeftAssign:
4097 case EOpBitShiftRightAssign:
4098 // Unsigned can be bit-shifted by signed and vice versa, but we need to
4099 // check that the basic type is an integer type.
4100 isBitShift = true;
4101 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
4102 {
4103 return false;
4104 }
4105 break;
4106 case EOpBitwiseAnd:
4107 case EOpBitwiseXor:
4108 case EOpBitwiseOr:
4109 case EOpBitwiseAndAssign:
4110 case EOpBitwiseXorAssign:
4111 case EOpBitwiseOrAssign:
4112 // It is enough to check the type of only one operand, since later it
4113 // is checked that the operand types match.
4114 if (!IsInteger(left->getBasicType()))
4115 {
4116 return false;
4117 }
4118 break;
4119 default:
4120 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004121 }
4122
4123 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
4124 // So the basic type should usually match.
4125 if (!isBitShift && left->getBasicType() != right->getBasicType())
4126 {
4127 return false;
4128 }
4129
Olli Etuaho63e1ec52016-08-18 22:05:12 +03004130 // Check that:
4131 // 1. Type sizes match exactly on ops that require that.
4132 // 2. Restrictions for structs that contain arrays or samplers are respected.
4133 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
Jamie Madillb98c3a82015-07-23 14:26:04 -04004134 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004135 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004136 case EOpAssign:
4137 case EOpInitialize:
4138 case EOpEqual:
4139 case EOpNotEqual:
4140 // ESSL 1.00 sections 5.7, 5.8, 5.9
4141 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
4142 {
4143 error(loc, "undefined operation for structs containing arrays",
4144 GetOperatorString(op));
4145 return false;
4146 }
4147 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
4148 // we interpret the spec so that this extends to structs containing samplers,
4149 // similarly to ESSL 1.00 spec.
4150 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
4151 left->getType().isStructureContainingSamplers())
4152 {
4153 error(loc, "undefined operation for structs containing samplers",
4154 GetOperatorString(op));
4155 return false;
4156 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004157
Olli Etuahoe1805592017-01-02 16:41:20 +00004158 if ((left->getNominalSize() != right->getNominalSize()) ||
4159 (left->getSecondarySize() != right->getSecondarySize()))
4160 {
4161 error(loc, "dimension mismatch", GetOperatorString(op));
4162 return false;
4163 }
4164 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004165 case EOpLessThan:
4166 case EOpGreaterThan:
4167 case EOpLessThanEqual:
4168 case EOpGreaterThanEqual:
Olli Etuahoe1805592017-01-02 16:41:20 +00004169 if (!left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04004170 {
Olli Etuahoe1805592017-01-02 16:41:20 +00004171 error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
Jamie Madillb98c3a82015-07-23 14:26:04 -04004172 return false;
4173 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03004174 break;
4175 case EOpAdd:
4176 case EOpSub:
4177 case EOpDiv:
4178 case EOpIMod:
4179 case EOpBitShiftLeft:
4180 case EOpBitShiftRight:
4181 case EOpBitwiseAnd:
4182 case EOpBitwiseXor:
4183 case EOpBitwiseOr:
4184 case EOpAddAssign:
4185 case EOpSubAssign:
4186 case EOpDivAssign:
4187 case EOpIModAssign:
4188 case EOpBitShiftLeftAssign:
4189 case EOpBitShiftRightAssign:
4190 case EOpBitwiseAndAssign:
4191 case EOpBitwiseXorAssign:
4192 case EOpBitwiseOrAssign:
4193 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
4194 {
4195 return false;
4196 }
4197
4198 // Are the sizes compatible?
4199 if (left->getNominalSize() != right->getNominalSize() ||
4200 left->getSecondarySize() != right->getSecondarySize())
4201 {
4202 // If the nominal sizes of operands do not match:
4203 // One of them must be a scalar.
4204 if (!left->isScalar() && !right->isScalar())
4205 return false;
4206
4207 // In the case of compound assignment other than multiply-assign,
4208 // the right side needs to be a scalar. Otherwise a vector/matrix
4209 // would be assigned to a scalar. A scalar can't be shifted by a
4210 // vector either.
4211 if (!right->isScalar() &&
4212 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
4213 return false;
4214 }
4215 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004216 default:
4217 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004218 }
4219
Olli Etuahod6b14282015-03-17 14:31:35 +02004220 return true;
4221}
4222
Olli Etuaho1dded802016-08-18 18:13:13 +03004223bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
4224 const TType &left,
4225 const TType &right)
4226{
4227 switch (op)
4228 {
4229 case EOpMul:
4230 case EOpMulAssign:
4231 return left.getNominalSize() == right.getNominalSize() &&
4232 left.getSecondarySize() == right.getSecondarySize();
4233 case EOpVectorTimesScalar:
4234 return true;
4235 case EOpVectorTimesScalarAssign:
4236 ASSERT(!left.isMatrix() && !right.isMatrix());
4237 return left.isVector() && !right.isVector();
4238 case EOpVectorTimesMatrix:
4239 return left.getNominalSize() == right.getRows();
4240 case EOpVectorTimesMatrixAssign:
4241 ASSERT(!left.isMatrix() && right.isMatrix());
4242 return left.isVector() && left.getNominalSize() == right.getRows() &&
4243 left.getNominalSize() == right.getCols();
4244 case EOpMatrixTimesVector:
4245 return left.getCols() == right.getNominalSize();
4246 case EOpMatrixTimesScalar:
4247 return true;
4248 case EOpMatrixTimesScalarAssign:
4249 ASSERT(left.isMatrix() && !right.isMatrix());
4250 return !right.isVector();
4251 case EOpMatrixTimesMatrix:
4252 return left.getCols() == right.getRows();
4253 case EOpMatrixTimesMatrixAssign:
4254 ASSERT(left.isMatrix() && right.isMatrix());
4255 // We need to check two things:
4256 // 1. The matrix multiplication step is valid.
4257 // 2. The result will have the same number of columns as the lvalue.
4258 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
4259
4260 default:
4261 UNREACHABLE();
4262 return false;
4263 }
4264}
4265
Jamie Madillb98c3a82015-07-23 14:26:04 -04004266TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
4267 TIntermTyped *left,
4268 TIntermTyped *right,
4269 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02004270{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004271 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004272 return nullptr;
4273
Olli Etuahofc1806e2015-03-17 13:03:11 +02004274 switch (op)
4275 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004276 case EOpEqual:
4277 case EOpNotEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04004278 case EOpLessThan:
4279 case EOpGreaterThan:
4280 case EOpLessThanEqual:
4281 case EOpGreaterThanEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04004282 break;
4283 case EOpLogicalOr:
4284 case EOpLogicalXor:
4285 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03004286 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4287 !right->getType().getStruct());
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00004288 if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04004289 {
4290 return nullptr;
4291 }
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00004292 // Basic types matching should have been already checked.
4293 ASSERT(right->getBasicType() == EbtBool);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004294 break;
4295 case EOpAdd:
4296 case EOpSub:
4297 case EOpDiv:
4298 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03004299 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4300 !right->getType().getStruct());
4301 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04004302 {
4303 return nullptr;
4304 }
4305 break;
4306 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03004307 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4308 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004309 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03004310 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04004311 {
4312 return nullptr;
4313 }
4314 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004315 default:
4316 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02004317 }
4318
Olli Etuaho1dded802016-08-18 18:13:13 +03004319 if (op == EOpMul)
4320 {
4321 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
4322 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4323 {
4324 return nullptr;
4325 }
4326 }
4327
Olli Etuaho3fdec912016-08-18 15:08:06 +03004328 TIntermBinary *node = new TIntermBinary(op, left, right);
4329 node->setLine(loc);
4330
Olli Etuaho3fdec912016-08-18 15:08:06 +03004331 // See if we can fold constants.
Olli Etuaho77ba4082016-12-16 12:01:18 +00004332 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuaho3fdec912016-08-18 15:08:06 +03004333 if (foldedNode)
4334 return foldedNode;
4335
4336 return node;
Olli Etuahofc1806e2015-03-17 13:03:11 +02004337}
4338
Jamie Madillb98c3a82015-07-23 14:26:04 -04004339TIntermTyped *TParseContext::addBinaryMath(TOperator op,
4340 TIntermTyped *left,
4341 TIntermTyped *right,
4342 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004343{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004344 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004345 if (node == 0)
4346 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004347 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4348 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02004349 return left;
4350 }
4351 return node;
4352}
4353
Jamie Madillb98c3a82015-07-23 14:26:04 -04004354TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
4355 TIntermTyped *left,
4356 TIntermTyped *right,
4357 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004358{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004359 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004360 if (node == 0)
4361 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004362 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4363 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04004364 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02004365 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004366 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
4367 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004368 }
4369 return node;
4370}
4371
Olli Etuaho13389b62016-10-16 11:48:18 +01004372TIntermBinary *TParseContext::createAssign(TOperator op,
4373 TIntermTyped *left,
4374 TIntermTyped *right,
4375 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004376{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004377 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004378 {
Olli Etuaho1dded802016-08-18 18:13:13 +03004379 if (op == EOpMulAssign)
4380 {
4381 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
4382 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4383 {
4384 return nullptr;
4385 }
4386 }
Olli Etuaho3fdec912016-08-18 15:08:06 +03004387 TIntermBinary *node = new TIntermBinary(op, left, right);
4388 node->setLine(loc);
4389
Olli Etuaho3fdec912016-08-18 15:08:06 +03004390 return node;
Olli Etuahod6b14282015-03-17 14:31:35 +02004391 }
4392 return nullptr;
4393}
4394
Jamie Madillb98c3a82015-07-23 14:26:04 -04004395TIntermTyped *TParseContext::addAssign(TOperator op,
4396 TIntermTyped *left,
4397 TIntermTyped *right,
4398 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004399{
4400 TIntermTyped *node = createAssign(op, left, right, loc);
4401 if (node == nullptr)
4402 {
4403 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02004404 return left;
4405 }
4406 return node;
4407}
4408
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004409TIntermTyped *TParseContext::addComma(TIntermTyped *left,
4410 TIntermTyped *right,
4411 const TSourceLoc &loc)
4412{
Corentin Wallez0d959252016-07-12 17:26:32 -04004413 // WebGL2 section 5.26, the following results in an error:
4414 // "Sequence operator applied to void, arrays, or structs containing arrays"
Jamie Madilld7b1ab52016-12-12 14:42:19 -05004415 if (mShaderSpec == SH_WEBGL2_SPEC &&
4416 (left->isArray() || left->getBasicType() == EbtVoid ||
4417 left->getType().isStructureContainingArrays() || right->isArray() ||
4418 right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
Corentin Wallez0d959252016-07-12 17:26:32 -04004419 {
4420 error(loc,
4421 "sequence operator is not allowed for void, arrays, or structs containing arrays",
4422 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04004423 }
4424
Olli Etuaho4db7ded2016-10-13 12:23:11 +01004425 return TIntermediate::AddComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004426}
4427
Olli Etuaho49300862015-02-20 14:54:49 +02004428TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
4429{
4430 switch (op)
4431 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004432 case EOpContinue:
4433 if (mLoopNestingLevel <= 0)
4434 {
4435 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004436 }
4437 break;
4438 case EOpBreak:
4439 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
4440 {
4441 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004442 }
4443 break;
4444 case EOpReturn:
4445 if (mCurrentFunctionType->getBasicType() != EbtVoid)
4446 {
4447 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004448 }
4449 break;
4450 default:
4451 // No checks for discard
4452 break;
Olli Etuaho49300862015-02-20 14:54:49 +02004453 }
4454 return intermediate.addBranch(op, loc);
4455}
4456
Jamie Madillb98c3a82015-07-23 14:26:04 -04004457TIntermBranch *TParseContext::addBranch(TOperator op,
4458 TIntermTyped *returnValue,
4459 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02004460{
4461 ASSERT(op == EOpReturn);
4462 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004463 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02004464 {
4465 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004466 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004467 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02004468 {
4469 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004470 }
4471 return intermediate.addBranch(op, returnValue, loc);
4472}
4473
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004474void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
4475{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004476 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Olli Etuahobd674552016-10-06 13:28:42 +01004477 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004478 TIntermNode *offset = nullptr;
4479 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuahoec9232b2017-03-27 17:01:37 +03004480 if (name == "texelFetchOffset" || name == "textureLodOffset" ||
4481 name == "textureProjLodOffset" || name == "textureGradOffset" ||
4482 name == "textureProjGradOffset")
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004483 {
4484 offset = arguments->back();
4485 }
Olli Etuahoec9232b2017-03-27 17:01:37 +03004486 else if (name == "textureOffset" || name == "textureProjOffset")
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004487 {
4488 // A bias parameter might follow the offset parameter.
4489 ASSERT(arguments->size() >= 3);
4490 offset = (*arguments)[2];
4491 }
4492 if (offset != nullptr)
4493 {
4494 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
4495 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
4496 {
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004497 error(functionCall->getLine(), "Texture offset must be a constant expression",
Olli Etuahoec9232b2017-03-27 17:01:37 +03004498 name.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004499 }
4500 else
4501 {
4502 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
4503 size_t size = offsetConstantUnion->getType().getObjectSize();
4504 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
4505 for (size_t i = 0u; i < size; ++i)
4506 {
4507 int offsetValue = values[i].getIConst();
4508 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
4509 {
4510 std::stringstream tokenStream;
4511 tokenStream << offsetValue;
4512 std::string token = tokenStream.str();
4513 error(offset->getLine(), "Texture offset value out of valid range",
4514 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004515 }
4516 }
4517 }
4518 }
4519}
4520
Martin Radev2cc85b32016-08-05 16:22:53 +03004521// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
4522void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
4523{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004524 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Martin Radev2cc85b32016-08-05 16:22:53 +03004525 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
4526
4527 if (name.compare(0, 5, "image") == 0)
4528 {
4529 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuaho485eefd2017-02-14 17:40:06 +00004530 TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
Martin Radev2cc85b32016-08-05 16:22:53 +03004531
Olli Etuaho485eefd2017-02-14 17:40:06 +00004532 const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
Martin Radev2cc85b32016-08-05 16:22:53 +03004533
4534 if (name.compare(5, 5, "Store") == 0)
4535 {
4536 if (memoryQualifier.readonly)
4537 {
4538 error(imageNode->getLine(),
4539 "'imageStore' cannot be used with images qualified as 'readonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004540 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03004541 }
4542 }
4543 else if (name.compare(5, 4, "Load") == 0)
4544 {
4545 if (memoryQualifier.writeonly)
4546 {
4547 error(imageNode->getLine(),
4548 "'imageLoad' cannot be used with images qualified as 'writeonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004549 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03004550 }
4551 }
4552 }
4553}
4554
4555// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
4556void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
4557 const TFunction *functionDefinition,
4558 const TIntermAggregate *functionCall)
4559{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004560 ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
Martin Radev2cc85b32016-08-05 16:22:53 +03004561
4562 const TIntermSequence &arguments = *functionCall->getSequence();
4563
4564 ASSERT(functionDefinition->getParamCount() == arguments.size());
4565
4566 for (size_t i = 0; i < arguments.size(); ++i)
4567 {
Olli Etuaho485eefd2017-02-14 17:40:06 +00004568 TIntermTyped *typedArgument = arguments[i]->getAsTyped();
4569 const TType &functionArgumentType = typedArgument->getType();
Martin Radev2cc85b32016-08-05 16:22:53 +03004570 const TType &functionParameterType = *functionDefinition->getParam(i).type;
4571 ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
4572
4573 if (IsImage(functionArgumentType.getBasicType()))
4574 {
4575 const TMemoryQualifier &functionArgumentMemoryQualifier =
4576 functionArgumentType.getMemoryQualifier();
4577 const TMemoryQualifier &functionParameterMemoryQualifier =
4578 functionParameterType.getMemoryQualifier();
4579 if (functionArgumentMemoryQualifier.readonly &&
4580 !functionParameterMemoryQualifier.readonly)
4581 {
4582 error(functionCall->getLine(),
4583 "Function call discards the 'readonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004584 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03004585 }
4586
4587 if (functionArgumentMemoryQualifier.writeonly &&
4588 !functionParameterMemoryQualifier.writeonly)
4589 {
4590 error(functionCall->getLine(),
4591 "Function call discards the 'writeonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004592 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03004593 }
Martin Radev049edfa2016-11-11 14:35:37 +02004594
4595 if (functionArgumentMemoryQualifier.coherent &&
4596 !functionParameterMemoryQualifier.coherent)
4597 {
4598 error(functionCall->getLine(),
4599 "Function call discards the 'coherent' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004600 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02004601 }
4602
4603 if (functionArgumentMemoryQualifier.volatileQualifier &&
4604 !functionParameterMemoryQualifier.volatileQualifier)
4605 {
4606 error(functionCall->getLine(),
4607 "Function call discards the 'volatile' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004608 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02004609 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004610 }
4611 }
4612}
4613
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004614TIntermSequence *TParseContext::createEmptyArgumentsList()
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004615{
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004616 return new TIntermSequence();
Olli Etuaho72d10202017-01-19 15:58:30 +00004617}
4618
4619TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004620 TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00004621 TIntermNode *thisNode,
4622 const TSourceLoc &loc)
4623{
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004624 if (thisNode != nullptr)
4625 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004626 return addMethod(fnCall, arguments, thisNode, loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004627 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004628
4629 TOperator op = fnCall->getBuiltInOp();
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004630 if (op == EOpConstruct)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004631 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004632 return addConstructor(arguments, fnCall->getReturnType(), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004633 }
4634 else
4635 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004636 ASSERT(op == EOpNull);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004637 return addNonConstructorFunctionCall(fnCall, arguments, loc);
4638 }
4639}
4640
4641TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
4642 TIntermSequence *arguments,
4643 TIntermNode *thisNode,
4644 const TSourceLoc &loc)
4645{
4646 TConstantUnion *unionArray = new TConstantUnion[1];
4647 int arraySize = 0;
4648 TIntermTyped *typedThis = thisNode->getAsTyped();
4649 // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
4650 // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
4651 // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
4652 // So accessing fnCall->getName() below is safe.
4653 if (fnCall->getName() != "length")
4654 {
4655 error(loc, "invalid method", fnCall->getName().c_str());
4656 }
4657 else if (!arguments->empty())
4658 {
4659 error(loc, "method takes no parameters", "length");
4660 }
4661 else if (typedThis == nullptr || !typedThis->isArray())
4662 {
4663 error(loc, "length can only be called on arrays", "length");
4664 }
4665 else
4666 {
4667 arraySize = typedThis->getArraySize();
4668 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuaho72d10202017-01-19 15:58:30 +00004669 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004670 // This code path can be hit with expressions like these:
4671 // (a = b).length()
4672 // (func()).length()
4673 // (int[3](0, 1, 2)).length()
4674 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
4675 // expression.
4676 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
4677 // spec section 5.9 which allows "An array, vector or matrix expression with the
4678 // length method applied".
4679 error(loc, "length can only be called on array names, not on array expressions",
4680 "length");
Olli Etuaho72d10202017-01-19 15:58:30 +00004681 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004682 }
4683 unionArray->setIConst(arraySize);
4684 return intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
4685}
4686
4687TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
4688 TIntermSequence *arguments,
4689 const TSourceLoc &loc)
4690{
4691 // First find by unmangled name to check whether the function name has been
4692 // hidden by a variable name or struct typename.
4693 // If a function is found, check for one with a matching argument list.
4694 bool builtIn;
4695 const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn);
4696 if (symbol != nullptr && !symbol->isFunction())
4697 {
4698 error(loc, "function name expected", fnCall->getName().c_str());
4699 }
4700 else
4701 {
4702 symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments),
4703 mShaderVersion, &builtIn);
4704 if (symbol == nullptr)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004705 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004706 error(loc, "no matching overloaded function found", fnCall->getName().c_str());
4707 }
4708 else
4709 {
4710 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004711 //
4712 // A declared function.
4713 //
Olli Etuaho383b7912016-08-05 11:22:59 +03004714 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004715 {
Olli Etuaho856c4972016-08-08 11:38:39 +03004716 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004717 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004718 TOperator op = fnCandidate->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004719 if (builtIn && op != EOpNull)
4720 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004721 // A function call mapped to a built-in operation.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004722 if (fnCandidate->getParamCount() == 1)
4723 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004724 // Treat it like a built-in unary operator.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004725 TIntermNode *unaryParamNode = arguments->front();
4726 TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004727 ASSERT(callNode != nullptr);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004728 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004729 }
4730 else
4731 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004732 TIntermAggregate *callNode =
Olli Etuahofe486322017-03-21 09:30:54 +00004733 TIntermAggregate::Create(fnCandidate->getReturnType(), op, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004734 callNode->setLine(loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004735
4736 // Some built-in functions have out parameters too.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004737 functionCallLValueErrorCheck(fnCandidate, callNode);
Arun Patole274f0702015-05-05 13:33:30 +05304738
Olli Etuaho7c3848e2015-11-04 13:19:17 +02004739 // See if we can constant fold a built-in. Note that this may be possible even
4740 // if it is not const-qualified.
Olli Etuahof119a262016-08-19 15:54:22 +03004741 TIntermTyped *foldedNode =
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004742 intermediate.foldAggregateBuiltIn(callNode, mDiagnostics);
Arun Patole274f0702015-05-05 13:33:30 +05304743 if (foldedNode)
4744 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004745 return foldedNode;
Arun Patole274f0702015-05-05 13:33:30 +05304746 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004747 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004748 }
4749 }
4750 else
4751 {
4752 // This is a real function call
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004753 TIntermAggregate *callNode = nullptr;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004754
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004755 // If builtIn == false, the function is user defined - could be an overloaded
4756 // built-in as well.
4757 // if builtIn == true, it's a builtIn function with no op associated with it.
4758 // This needs to happen after the function info including name is set.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004759 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004760 {
Olli Etuahofe486322017-03-21 09:30:54 +00004761 callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004762 checkTextureOffsetConst(callNode);
4763 checkImageMemoryAccessForBuiltinFunctions(callNode);
Martin Radev2cc85b32016-08-05 16:22:53 +03004764 }
4765 else
4766 {
Olli Etuahofe486322017-03-21 09:30:54 +00004767 callNode = TIntermAggregate::CreateFunctionCall(*fnCandidate, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004768 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004769 }
4770
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004771 functionCallLValueErrorCheck(fnCandidate, callNode);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004772
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004773 callNode->setLine(loc);
4774
4775 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004776 }
4777 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004778 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004779
4780 // Error message was already written. Put on a dummy node for error recovery.
4781 return TIntermTyped::CreateZero(TType(EbtFloat, EbpMedium, EvqConst));
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004782}
4783
Jamie Madillb98c3a82015-07-23 14:26:04 -04004784TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004785 TIntermTyped *trueExpression,
4786 TIntermTyped *falseExpression,
Olli Etuaho52901742015-04-15 13:42:45 +03004787 const TSourceLoc &loc)
4788{
Olli Etuaho856c4972016-08-08 11:38:39 +03004789 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03004790
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004791 if (trueExpression->getType() != falseExpression->getType())
Olli Etuaho52901742015-04-15 13:42:45 +03004792 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004793 binaryOpError(loc, "?:", trueExpression->getCompleteString(),
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004794 falseExpression->getCompleteString());
4795 return falseExpression;
Olli Etuaho52901742015-04-15 13:42:45 +03004796 }
Olli Etuahode318b22016-10-25 16:18:25 +01004797 if (IsOpaqueType(trueExpression->getBasicType()))
4798 {
4799 // ESSL 1.00 section 4.1.7
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004800 // ESSL 3.00.6 section 4.1.7
Olli Etuahode318b22016-10-25 16:18:25 +01004801 // Opaque/sampler types are not allowed in most types of expressions, including ternary.
4802 // Note that structs containing opaque types don't need to be checked as structs are
4803 // forbidden below.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004804 error(loc, "ternary operator is not allowed for opaque types", "?:");
Olli Etuahode318b22016-10-25 16:18:25 +01004805 return falseExpression;
4806 }
4807
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004808 // ESSL 1.00.17 sections 5.2 and 5.7:
Olli Etuahoa2d53032015-04-15 14:14:44 +03004809 // Ternary operator is not among the operators allowed for structures/arrays.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004810 // ESSL 3.00.6 section 5.7:
4811 // Ternary operator support is optional for arrays. No certainty that it works across all
4812 // devices with struct either, so we err on the side of caution here. TODO (oetuaho@nvidia.com):
4813 // Would be nice to make the spec and implementation agree completely here.
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004814 if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
Olli Etuahoa2d53032015-04-15 14:14:44 +03004815 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004816 error(loc, "ternary operator is not allowed for structures or arrays", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004817 return falseExpression;
Olli Etuahoa2d53032015-04-15 14:14:44 +03004818 }
Olli Etuaho94050052017-05-08 14:17:44 +03004819 if (trueExpression->getBasicType() == EbtInterfaceBlock)
4820 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004821 error(loc, "ternary operator is not allowed for interface blocks", "?:");
Olli Etuaho94050052017-05-08 14:17:44 +03004822 return falseExpression;
4823 }
4824
Corentin Wallez0d959252016-07-12 17:26:32 -04004825 // WebGL2 section 5.26, the following results in an error:
4826 // "Ternary operator applied to void, arrays, or structs containing arrays"
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004827 if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
Corentin Wallez0d959252016-07-12 17:26:32 -04004828 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004829 error(loc, "ternary operator is not allowed for void", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004830 return falseExpression;
Corentin Wallez0d959252016-07-12 17:26:32 -04004831 }
4832
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004833 return TIntermediate::AddTernarySelection(cond, trueExpression, falseExpression, loc);
Olli Etuaho52901742015-04-15 13:42:45 +03004834}
Olli Etuaho49300862015-02-20 14:54:49 +02004835
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004836//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004837// Parse an array of strings using yyparse.
4838//
4839// Returns 0 for success.
4840//
Jamie Madillb98c3a82015-07-23 14:26:04 -04004841int PaParseStrings(size_t count,
4842 const char *const string[],
4843 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05304844 TParseContext *context)
4845{
Yunchao He4f285442017-04-21 12:15:49 +08004846 if ((count == 0) || (string == nullptr))
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004847 return 1;
4848
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004849 if (glslang_initialize(context))
4850 return 1;
4851
alokp@chromium.org408c45e2012-04-05 15:54:43 +00004852 int error = glslang_scan(count, string, length, context);
4853 if (!error)
4854 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004855
alokp@chromium.org73bc2982012-06-19 18:48:05 +00004856 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00004857
alokp@chromium.org6b495712012-06-29 00:06:58 +00004858 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004859}
Jamie Madill45bcc782016-11-07 13:58:48 -05004860
4861} // namespace sh