blob: f3bd17997445588ba6d436266f91c4a838eddd34 [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//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001677// Initializers show up in several places in the grammar. Have one set of
1678// code to handle them here.
1679//
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001680// Returns true on error, false if no error
1681//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001682bool TParseContext::executeInitializer(const TSourceLoc &line,
1683 const TString &identifier,
1684 const TPublicType &pType,
1685 TIntermTyped *initializer,
Olli Etuaho13389b62016-10-16 11:48:18 +01001686 TIntermBinary **initNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001687{
Olli Etuaho13389b62016-10-16 11:48:18 +01001688 ASSERT(initNode != nullptr);
1689 ASSERT(*initNode == nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001690 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001691
Olli Etuaho2935c582015-04-08 14:32:06 +03001692 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001693 if (type.isUnsizedArray())
1694 {
Olli Etuaho02bd82c2016-11-03 10:29:43 +00001695 // We have not checked yet whether the initializer actually is an array or not.
1696 if (initializer->isArray())
1697 {
1698 type.setArraySize(initializer->getArraySize());
1699 }
1700 else
1701 {
1702 // Having a non-array initializer for an unsized array will result in an error later,
1703 // so we don't generate an error message here.
1704 type.setArraySize(1u);
1705 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03001706 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001707 if (!declareVariable(line, identifier, type, &variable))
1708 {
1709 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001710 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001711
Olli Etuahob0c645e2015-05-12 14:25:36 +03001712 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001713 if (symbolTable.atGlobalLevel() &&
1714 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001715 {
1716 // Error message does not completely match behavior with ESSL 1.00, but
1717 // we want to steer developers towards only using constant expressions.
1718 error(line, "global variable initializers must be constant expressions", "=");
1719 return true;
1720 }
1721 if (globalInitWarning)
1722 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001723 warning(
1724 line,
1725 "global variable initializers should be constant expressions "
1726 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1727 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001728 }
1729
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001730 //
1731 // identifier must be of type constant, a global, or a temporary
1732 //
1733 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301734 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1735 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001736 error(line, " cannot initialize this type of qualifier ",
1737 variable->getType().getQualifierString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001738 return true;
1739 }
1740 //
1741 // test for and propagate constant
1742 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001743
Arun Patole7e7e68d2015-05-22 12:02:25 +05301744 if (qualifier == EvqConst)
1745 {
1746 if (qualifier != initializer->getType().getQualifier())
1747 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001748 std::stringstream reasonStream;
1749 reasonStream << "assigning non-constant to '" << variable->getType().getCompleteString()
1750 << "'";
1751 std::string reason = reasonStream.str();
1752 error(line, reason.c_str(), "=");
alokp@chromium.org58e54292010-08-24 21:40:03 +00001753 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001754 return true;
1755 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301756 if (type != initializer->getType())
1757 {
1758 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001759 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001760 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001761 return true;
1762 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001763
1764 // Save the constant folded value to the variable if possible. For example array
1765 // initializers are not folded, since that way copying the array literal to multiple places
1766 // in the shader is avoided.
1767 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1768 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301769 if (initializer->getAsConstantUnion())
1770 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001771 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuaho13389b62016-10-16 11:48:18 +01001772 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001773 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301774 }
1775 else if (initializer->getAsSymbolNode())
1776 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001777 const TSymbol *symbol =
1778 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1779 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001780
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001781 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001782 if (constArray)
1783 {
1784 variable->shareConstPointer(constArray);
Olli Etuaho13389b62016-10-16 11:48:18 +01001785 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001786 return false;
1787 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001788 }
1789 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001790
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001791 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1792 variable->getUniqueId(), variable->getName(), variable->getType(), line);
Olli Etuaho13389b62016-10-16 11:48:18 +01001793 *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1794 if (*initNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001795 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001796 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1797 return true;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001798 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001799
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001800 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001801}
1802
Olli Etuaho0e3aee32016-10-27 12:56:38 +01001803void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
1804{
1805 checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
1806 typeSpecifier->getBasicType());
1807
1808 if (mShaderVersion < 300 && typeSpecifier->array)
1809 {
1810 error(typeSpecifier->getLine(), "not supported", "first-class array");
1811 typeSpecifier->clearArrayness();
1812 }
1813}
1814
Martin Radev70866b82016-07-22 15:27:42 +03001815TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301816 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001817{
Olli Etuaho77ba4082016-12-16 12:01:18 +00001818 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001819
Martin Radev70866b82016-07-22 15:27:42 +03001820 TPublicType returnType = typeSpecifier;
1821 returnType.qualifier = typeQualifier.qualifier;
1822 returnType.invariant = typeQualifier.invariant;
1823 returnType.layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03001824 returnType.memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03001825 returnType.precision = typeSpecifier.precision;
1826
1827 if (typeQualifier.precision != EbpUndefined)
1828 {
1829 returnType.precision = typeQualifier.precision;
1830 }
1831
Martin Radev4a9cd802016-09-01 16:51:51 +03001832 checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
1833 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03001834
Martin Radev4a9cd802016-09-01 16:51:51 +03001835 checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
1836 typeSpecifier.getLine());
Martin Radev70866b82016-07-22 15:27:42 +03001837
Martin Radev4a9cd802016-09-01 16:51:51 +03001838 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001839
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001840 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001841 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001842 if (typeSpecifier.array)
1843 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001844 error(typeSpecifier.getLine(), "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001845 returnType.clearArrayness();
1846 }
1847
Martin Radev70866b82016-07-22 15:27:42 +03001848 if (returnType.qualifier == EvqAttribute &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001849 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001850 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001851 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001852 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001853 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001854
Martin Radev70866b82016-07-22 15:27:42 +03001855 if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001856 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001857 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001858 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001859 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001860 }
1861 }
1862 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001863 {
Martin Radev70866b82016-07-22 15:27:42 +03001864 if (!returnType.layoutQualifier.isEmpty())
Olli Etuahoabb0c382015-07-13 12:01:12 +03001865 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001866 checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03001867 }
Martin Radev70866b82016-07-22 15:27:42 +03001868 if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
1869 returnType.qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001870 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001871 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
1872 typeSpecifier.getLine());
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001873 }
Martin Radev70866b82016-07-22 15:27:42 +03001874 if (returnType.qualifier == EvqComputeIn)
Martin Radev802abe02016-08-04 17:48:32 +03001875 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001876 error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
Martin Radev802abe02016-08-04 17:48:32 +03001877 "in");
Martin Radev802abe02016-08-04 17:48:32 +03001878 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001879 }
1880
1881 return returnType;
1882}
1883
Olli Etuaho856c4972016-08-08 11:38:39 +03001884void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1885 const TPublicType &type,
1886 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03001887{
1888 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
Martin Radev4a9cd802016-09-01 16:51:51 +03001889 if (type.getBasicType() == EbtBool)
Olli Etuahocc36b982015-07-10 14:14:18 +03001890 {
1891 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001892 }
1893
1894 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1895 switch (qualifier)
1896 {
1897 case EvqVertexIn:
1898 // ESSL 3.00 section 4.3.4
1899 if (type.array)
1900 {
1901 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001902 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001903 // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03001904 return;
1905 case EvqFragmentOut:
1906 // ESSL 3.00 section 4.3.6
Martin Radev4a9cd802016-09-01 16:51:51 +03001907 if (type.typeSpecifierNonArray.isMatrix())
Olli Etuahocc36b982015-07-10 14:14:18 +03001908 {
1909 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001910 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001911 // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03001912 return;
1913 default:
1914 break;
1915 }
1916
1917 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1918 // restrictions.
1919 bool typeContainsIntegers =
Martin Radev4a9cd802016-09-01 16:51:51 +03001920 (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
1921 type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
Olli Etuahocc36b982015-07-10 14:14:18 +03001922 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1923 {
1924 error(qualifierLocation, "must use 'flat' interpolation here",
1925 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001926 }
1927
Martin Radev4a9cd802016-09-01 16:51:51 +03001928 if (type.getBasicType() == EbtStruct)
Olli Etuahocc36b982015-07-10 14:14:18 +03001929 {
1930 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1931 // These restrictions are only implied by the ESSL 3.00 spec, but
1932 // the ESSL 3.10 spec lists these restrictions explicitly.
1933 if (type.array)
1934 {
1935 error(qualifierLocation, "cannot be an array of structures",
1936 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001937 }
1938 if (type.isStructureContainingArrays())
1939 {
1940 error(qualifierLocation, "cannot be a structure containing an array",
1941 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001942 }
1943 if (type.isStructureContainingType(EbtStruct))
1944 {
1945 error(qualifierLocation, "cannot be a structure containing a structure",
1946 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001947 }
1948 if (type.isStructureContainingType(EbtBool))
1949 {
1950 error(qualifierLocation, "cannot be a structure containing a bool",
1951 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001952 }
1953 }
1954}
1955
Martin Radev2cc85b32016-08-05 16:22:53 +03001956void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
1957{
1958 if (qualifier.getType() == QtStorage)
1959 {
1960 const TStorageQualifierWrapper &storageQualifier =
1961 static_cast<const TStorageQualifierWrapper &>(qualifier);
1962 if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
1963 !symbolTable.atGlobalLevel())
1964 {
1965 error(storageQualifier.getLine(),
1966 "Local variables can only use the const storage qualifier.",
1967 storageQualifier.getQualifierString().c_str());
1968 }
1969 }
1970}
1971
Olli Etuaho43364892017-02-13 16:00:12 +00001972void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
Martin Radev2cc85b32016-08-05 16:22:53 +03001973 const TSourceLoc &location)
1974{
1975 if (memoryQualifier.readonly)
1976 {
1977 error(location, "Only allowed with images.", "readonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03001978 }
1979 if (memoryQualifier.writeonly)
1980 {
1981 error(location, "Only allowed with images.", "writeonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03001982 }
Martin Radev049edfa2016-11-11 14:35:37 +02001983 if (memoryQualifier.coherent)
1984 {
1985 error(location, "Only allowed with images.", "coherent");
Martin Radev049edfa2016-11-11 14:35:37 +02001986 }
1987 if (memoryQualifier.restrictQualifier)
1988 {
1989 error(location, "Only allowed with images.", "restrict");
Martin Radev049edfa2016-11-11 14:35:37 +02001990 }
1991 if (memoryQualifier.volatileQualifier)
1992 {
1993 error(location, "Only allowed with images.", "volatile");
Martin Radev049edfa2016-11-11 14:35:37 +02001994 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001995}
1996
jchen104cdac9e2017-05-08 11:01:20 +08001997// Make sure there is no offset overlapping, and store the newly assigned offset to "type" in
1998// intermediate tree.
1999void TParseContext::checkAtomicCounterOffsetIsNotOverlapped(TPublicType &publicType,
2000 size_t size,
2001 bool forceAppend,
2002 const TSourceLoc &loc,
2003 TType &type)
2004{
2005 auto &bindingState = mAtomicCounterBindingStates[publicType.layoutQualifier.binding];
2006 int offset;
2007 if (publicType.layoutQualifier.offset == -1 || forceAppend)
2008 {
2009 offset = bindingState.appendSpan(size);
2010 }
2011 else
2012 {
2013 offset = bindingState.insertSpan(publicType.layoutQualifier.offset, size);
2014 }
2015 if (offset == -1)
2016 {
2017 error(loc, "Offset overlapping", "atomic counter");
2018 return;
2019 }
2020 TLayoutQualifier qualifier = type.getLayoutQualifier();
2021 qualifier.offset = offset;
2022 type.setLayoutQualifier(qualifier);
2023}
2024
Olli Etuaho13389b62016-10-16 11:48:18 +01002025TIntermDeclaration *TParseContext::parseSingleDeclaration(
2026 TPublicType &publicType,
2027 const TSourceLoc &identifierOrTypeLocation,
2028 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04002029{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07002030 TType type(publicType);
2031 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
2032 mDirectiveHandler.pragma().stdgl.invariantAll)
2033 {
2034 TQualifier qualifier = type.getQualifier();
2035
2036 // The directive handler has already taken care of rejecting invalid uses of this pragma
2037 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
2038 // affected variable declarations:
2039 //
2040 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
2041 // elsewhere, in TranslatorGLSL.)
2042 //
2043 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
2044 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
2045 // the way this is currently implemented we have to enable this compiler option before
2046 // parsing the shader and determining the shading language version it uses. If this were
2047 // implemented as a post-pass, the workaround could be more targeted.
2048 //
2049 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
2050 // the specification, but there are desktop OpenGL drivers that expect that this is the
2051 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
2052 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
2053 {
2054 type.setInvariant(true);
2055 }
2056 }
2057
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002058 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2059 identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002060
Olli Etuahobab4c082015-04-24 16:38:49 +03002061 bool emptyDeclaration = (identifier == "");
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002062 mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration;
Olli Etuahofa33d582015-04-09 14:33:12 +03002063
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002064 TIntermSymbol *symbol = nullptr;
Olli Etuahobab4c082015-04-24 16:38:49 +03002065 if (emptyDeclaration)
2066 {
Martin Radevb8b01222016-11-20 23:25:53 +02002067 emptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002068 // In most cases we don't need to create a symbol node for an empty declaration.
2069 // But if the empty declaration is declaring a struct type, the symbol node will store that.
2070 if (type.getBasicType() == EbtStruct)
2071 {
2072 symbol = intermediate.addSymbol(0, "", type, identifierOrTypeLocation);
2073 }
jchen104cdac9e2017-05-08 11:01:20 +08002074 else if (IsAtomicCounter(publicType.getBasicType()))
2075 {
2076 setAtomicCounterBindingDefaultOffset(publicType, identifierOrTypeLocation);
2077 }
Olli Etuahobab4c082015-04-24 16:38:49 +03002078 }
2079 else
Jamie Madill60ed9812013-06-06 11:56:46 -04002080 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002081 nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002082
Olli Etuaho856c4972016-08-08 11:38:39 +03002083 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002084
jchen104cdac9e2017-05-08 11:01:20 +08002085 if (IsAtomicCounter(publicType.getBasicType()))
2086 {
2087
2088 checkAtomicCounterOffsetIsNotOverlapped(publicType, kAtomicCounterSize, false,
2089 identifierOrTypeLocation, type);
2090 }
2091
Olli Etuaho2935c582015-04-08 14:32:06 +03002092 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07002093 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04002094
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002095 if (variable)
Olli Etuaho13389b62016-10-16 11:48:18 +01002096 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002097 symbol = intermediate.addSymbol(variable->getUniqueId(), identifier, type,
2098 identifierOrTypeLocation);
Olli Etuaho13389b62016-10-16 11:48:18 +01002099 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002100 }
2101
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002102 TIntermDeclaration *declaration = new TIntermDeclaration();
2103 declaration->setLine(identifierOrTypeLocation);
2104 if (symbol)
2105 {
2106 declaration->appendDeclarator(symbol);
2107 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002108 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002109}
2110
Olli Etuaho13389b62016-10-16 11:48:18 +01002111TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
2112 const TSourceLoc &identifierLocation,
2113 const TString &identifier,
2114 const TSourceLoc &indexLocation,
2115 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04002116{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002117 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002118
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002119 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2120 identifierLocation);
2121
2122 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002123
Olli Etuaho856c4972016-08-08 11:38:39 +03002124 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002125
Olli Etuaho8a176262016-08-16 14:23:01 +03002126 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002127
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002128 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002129
Olli Etuaho856c4972016-08-08 11:38:39 +03002130 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002131 // Make the type an array even if size check failed.
2132 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2133 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04002134
jchen104cdac9e2017-05-08 11:01:20 +08002135 if (IsAtomicCounter(publicType.getBasicType()))
2136 {
2137 checkAtomicCounterOffsetIsNotOverlapped(publicType, kAtomicCounterArrayStride * size, false,
2138 identifierLocation, arrayType);
2139 }
2140
Olli Etuaho2935c582015-04-08 14:32:06 +03002141 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002142 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04002143
Olli Etuaho13389b62016-10-16 11:48:18 +01002144 TIntermDeclaration *declaration = new TIntermDeclaration();
2145 declaration->setLine(identifierLocation);
2146
Olli Etuahoe7847b02015-03-16 11:56:12 +02002147 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002148 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002149 {
Jamie Madill60ed9812013-06-06 11:56:46 -04002150 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002151 declaration->appendDeclarator(symbol);
2152 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002153
Olli Etuaho13389b62016-10-16 11:48:18 +01002154 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002155}
2156
Olli Etuaho13389b62016-10-16 11:48:18 +01002157TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
2158 const TSourceLoc &identifierLocation,
2159 const TString &identifier,
2160 const TSourceLoc &initLocation,
2161 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04002162{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002163 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002164
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002165 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2166 identifierLocation);
2167
2168 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002169
Olli Etuaho13389b62016-10-16 11:48:18 +01002170 TIntermDeclaration *declaration = new TIntermDeclaration();
2171 declaration->setLine(identifierLocation);
2172
2173 TIntermBinary *initNode = nullptr;
2174 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04002175 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002176 if (initNode)
2177 {
2178 declaration->appendDeclarator(initNode);
2179 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002180 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002181 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002182}
2183
Olli Etuaho13389b62016-10-16 11:48:18 +01002184TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
Jamie Madillb98c3a82015-07-23 14:26:04 -04002185 TPublicType &publicType,
2186 const TSourceLoc &identifierLocation,
2187 const TString &identifier,
2188 const TSourceLoc &indexLocation,
2189 TIntermTyped *indexExpression,
2190 const TSourceLoc &initLocation,
2191 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002192{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002193 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002194
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002195 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2196 identifierLocation);
2197
2198 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002199
Olli Etuaho8a176262016-08-16 14:23:01 +03002200 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002201
2202 TPublicType arrayType(publicType);
2203
Olli Etuaho856c4972016-08-08 11:38:39 +03002204 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002205 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2206 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002207 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002208 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002209 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002210 }
2211 // Make the type an array even if size check failed.
2212 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2213 arrayType.setArraySize(size);
2214
Olli Etuaho13389b62016-10-16 11:48:18 +01002215 TIntermDeclaration *declaration = new TIntermDeclaration();
2216 declaration->setLine(identifierLocation);
2217
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002218 // initNode will correspond to the whole of "type b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002219 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002220 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2221 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002222 if (initNode)
2223 {
2224 declaration->appendDeclarator(initNode);
2225 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002226 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002227
2228 return declaration;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002229}
2230
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002231TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
Martin Radev70866b82016-07-22 15:27:42 +03002232 const TTypeQualifierBuilder &typeQualifierBuilder,
2233 const TSourceLoc &identifierLoc,
2234 const TString *identifier,
2235 const TSymbol *symbol)
Jamie Madill47e3ec02014-08-20 16:38:33 -04002236{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002237 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002238
Martin Radev70866b82016-07-22 15:27:42 +03002239 if (!typeQualifier.invariant)
2240 {
2241 error(identifierLoc, "Expected invariant", identifier->c_str());
2242 return nullptr;
2243 }
2244 if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
2245 {
2246 return nullptr;
2247 }
Jamie Madill47e3ec02014-08-20 16:38:33 -04002248 if (!symbol)
2249 {
2250 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002251 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04002252 }
Martin Radev70866b82016-07-22 15:27:42 +03002253 if (!IsQualifierUnspecified(typeQualifier.qualifier))
Jamie Madill47e3ec02014-08-20 16:38:33 -04002254 {
Martin Radev70866b82016-07-22 15:27:42 +03002255 error(identifierLoc, "invariant declaration specifies qualifier",
2256 getQualifierString(typeQualifier.qualifier));
Jamie Madill47e3ec02014-08-20 16:38:33 -04002257 }
Martin Radev70866b82016-07-22 15:27:42 +03002258 if (typeQualifier.precision != EbpUndefined)
2259 {
2260 error(identifierLoc, "invariant declaration specifies precision",
2261 getPrecisionString(typeQualifier.precision));
2262 }
2263 if (!typeQualifier.layoutQualifier.isEmpty())
2264 {
2265 error(identifierLoc, "invariant declaration specifies layout", "'layout'");
2266 }
2267
2268 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
2269 ASSERT(variable);
2270 const TType &type = variable->getType();
2271
2272 checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
2273 typeQualifier.line);
Olli Etuaho43364892017-02-13 16:00:12 +00002274 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev70866b82016-07-22 15:27:42 +03002275
2276 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
2277
2278 TIntermSymbol *intermSymbol =
2279 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
2280
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002281 return new TIntermInvariantDeclaration(intermSymbol, identifierLoc);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002282}
2283
Olli Etuaho13389b62016-10-16 11:48:18 +01002284void TParseContext::parseDeclarator(TPublicType &publicType,
2285 const TSourceLoc &identifierLocation,
2286 const TString &identifier,
2287 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002288{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002289 // If the declaration starting this declarator list was empty (example: int,), some checks were
2290 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002291 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002292 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002293 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2294 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002295 }
2296
Olli Etuaho856c4972016-08-08 11:38:39 +03002297 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002298
Olli Etuaho856c4972016-08-08 11:38:39 +03002299 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002300
Olli Etuaho2935c582015-04-08 14:32:06 +03002301 TVariable *variable = nullptr;
Olli Etuaho43364892017-02-13 16:00:12 +00002302 TType type(publicType);
jchen104cdac9e2017-05-08 11:01:20 +08002303 if (IsAtomicCounter(publicType.getBasicType()))
2304 {
2305 checkAtomicCounterOffsetIsNotOverlapped(publicType, kAtomicCounterSize, true,
2306 identifierLocation, type);
2307 }
Olli Etuaho43364892017-02-13 16:00:12 +00002308 declareVariable(identifierLocation, identifier, type, &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002309
Olli Etuaho43364892017-02-13 16:00:12 +00002310 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002311 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002312 {
Jamie Madill502d66f2013-06-20 11:55:52 -04002313 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002314 declarationOut->appendDeclarator(symbol);
2315 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002316}
2317
Olli Etuaho13389b62016-10-16 11:48:18 +01002318void TParseContext::parseArrayDeclarator(TPublicType &publicType,
2319 const TSourceLoc &identifierLocation,
2320 const TString &identifier,
2321 const TSourceLoc &arrayLocation,
2322 TIntermTyped *indexExpression,
2323 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002324{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002325 // If the declaration starting this declarator list was empty (example: int,), some checks were
2326 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002327 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002328 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002329 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2330 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002331 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002332
Olli Etuaho856c4972016-08-08 11:38:39 +03002333 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002334
Olli Etuaho856c4972016-08-08 11:38:39 +03002335 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002336
Olli Etuaho8a176262016-08-16 14:23:01 +03002337 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04002338 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002339 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03002340 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03002341 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002342
jchen104cdac9e2017-05-08 11:01:20 +08002343 if (IsAtomicCounter(publicType.getBasicType()))
2344 {
2345 checkAtomicCounterOffsetIsNotOverlapped(publicType, kAtomicCounterArrayStride * size,
2346 true, identifierLocation, arrayType);
2347 }
2348
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002349 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002350 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04002351
Jamie Madillb98c3a82015-07-23 14:26:04 -04002352 TIntermSymbol *symbol =
2353 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002354 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002355 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002356
Olli Etuaho13389b62016-10-16 11:48:18 +01002357 declarationOut->appendDeclarator(symbol);
Jamie Madill502d66f2013-06-20 11:55:52 -04002358 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002359}
2360
Olli Etuaho13389b62016-10-16 11:48:18 +01002361void TParseContext::parseInitDeclarator(const TPublicType &publicType,
2362 const TSourceLoc &identifierLocation,
2363 const TString &identifier,
2364 const TSourceLoc &initLocation,
2365 TIntermTyped *initializer,
2366 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002367{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002368 // If the declaration starting this declarator list was empty (example: int,), some checks were
2369 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002370 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002371 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002372 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2373 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002374 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002375
Olli Etuaho856c4972016-08-08 11:38:39 +03002376 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002377
Olli Etuaho13389b62016-10-16 11:48:18 +01002378 TIntermBinary *initNode = nullptr;
2379 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04002380 {
2381 //
2382 // build the intermediate representation
2383 //
Olli Etuaho13389b62016-10-16 11:48:18 +01002384 if (initNode)
Jamie Madill502d66f2013-06-20 11:55:52 -04002385 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002386 declarationOut->appendDeclarator(initNode);
Jamie Madill502d66f2013-06-20 11:55:52 -04002387 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002388 }
2389}
2390
Olli Etuaho13389b62016-10-16 11:48:18 +01002391void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
2392 const TSourceLoc &identifierLocation,
2393 const TString &identifier,
2394 const TSourceLoc &indexLocation,
2395 TIntermTyped *indexExpression,
2396 const TSourceLoc &initLocation,
2397 TIntermTyped *initializer,
2398 TIntermDeclaration *declarationOut)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002399{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002400 // If the declaration starting this declarator list was empty (example: int,), some checks were
2401 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002402 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002403 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002404 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2405 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002406 }
2407
Olli Etuaho856c4972016-08-08 11:38:39 +03002408 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002409
Olli Etuaho8a176262016-08-16 14:23:01 +03002410 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002411
2412 TPublicType arrayType(publicType);
2413
Olli Etuaho856c4972016-08-08 11:38:39 +03002414 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002415 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2416 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002417 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002418 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002419 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002420 }
2421 // Make the type an array even if size check failed.
2422 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2423 arrayType.setArraySize(size);
2424
2425 // initNode will correspond to the whole of "b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002426 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002427 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2428 {
2429 if (initNode)
2430 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002431 declarationOut->appendDeclarator(initNode);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002432 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002433 }
2434}
2435
jchen104cdac9e2017-05-08 11:01:20 +08002436void TParseContext::setAtomicCounterBindingDefaultOffset(const TPublicType &publicType,
2437 const TSourceLoc &location)
2438{
2439 const TLayoutQualifier &layoutQualifier = publicType.layoutQualifier;
2440 checkAtomicCounterBindingIsValid(location, layoutQualifier.binding);
2441 if (layoutQualifier.binding == -1 || layoutQualifier.offset == -1)
2442 {
2443 error(location, "Requires both binding and offset", "layout");
2444 return;
2445 }
2446 mAtomicCounterBindingStates[layoutQualifier.binding].setDefaultOffset(layoutQualifier.offset);
2447}
2448
Martin Radev70866b82016-07-22 15:27:42 +03002449void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
Jamie Madilla295edf2013-06-06 11:56:48 -04002450{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002451 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madilla295edf2013-06-06 11:56:48 -04002452 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04002453
Martin Radev70866b82016-07-22 15:27:42 +03002454 checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
2455 typeQualifier.line);
2456
Jamie Madillc2128ff2016-07-04 10:26:17 -04002457 // It should never be the case, but some strange parser errors can send us here.
2458 if (layoutQualifier.isEmpty())
2459 {
2460 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04002461 return;
2462 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002463
Martin Radev802abe02016-08-04 17:48:32 +03002464 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04002465 {
Olli Etuaho43364892017-02-13 16:00:12 +00002466 error(typeQualifier.line, "invalid layout qualifier combination", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04002467 return;
2468 }
2469
Olli Etuaho43364892017-02-13 16:00:12 +00002470 checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);
2471
2472 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev2cc85b32016-08-05 16:22:53 +03002473
2474 checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
2475
Andrei Volykhina5527072017-03-22 16:46:30 +03002476 checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv);
2477
jchen104cdac9e2017-05-08 11:01:20 +08002478 checkOffsetIsNotSpecified(typeQualifier.line, layoutQualifier.offset);
2479
Martin Radev802abe02016-08-04 17:48:32 +03002480 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04002481 {
Martin Radev802abe02016-08-04 17:48:32 +03002482 if (mComputeShaderLocalSizeDeclared &&
2483 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
2484 {
2485 error(typeQualifier.line, "Work group size does not match the previous declaration",
2486 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002487 return;
2488 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002489
Martin Radev802abe02016-08-04 17:48:32 +03002490 if (mShaderVersion < 310)
2491 {
2492 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002493 return;
2494 }
Jamie Madill099c0f32013-06-20 11:55:52 -04002495
Martin Radev4c4c8e72016-08-04 12:25:34 +03002496 if (!layoutQualifier.localSize.isAnyValueSet())
Martin Radev802abe02016-08-04 17:48:32 +03002497 {
2498 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002499 return;
2500 }
2501
2502 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
2503 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
2504
2505 const TConstantUnion *maxComputeWorkGroupSizeData =
2506 maxComputeWorkGroupSize->getConstPointer();
2507
2508 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
2509 {
2510 if (layoutQualifier.localSize[i] != -1)
2511 {
2512 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
2513 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
2514 if (mComputeShaderLocalSize[i] < 1 ||
2515 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
2516 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002517 std::stringstream reasonStream;
2518 reasonStream << "invalid value: Value must be at least 1 and no greater than "
2519 << maxComputeWorkGroupSizeValue;
2520 const std::string &reason = reasonStream.str();
Martin Radev802abe02016-08-04 17:48:32 +03002521
Olli Etuaho4de340a2016-12-16 09:32:03 +00002522 error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03002523 return;
2524 }
2525 }
2526 }
2527
2528 mComputeShaderLocalSizeDeclared = true;
2529 }
Olli Etuaho95468d12017-05-04 11:14:34 +03002530 else if (isMultiviewExtensionEnabled() && typeQualifier.qualifier == EvqVertexIn)
Olli Etuaho09b04a22016-12-15 13:30:26 +00002531 {
2532 // This error is only specified in WebGL, but tightens unspecified behavior in the native
2533 // specification.
2534 if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
2535 {
2536 error(typeQualifier.line, "Number of views does not match the previous declaration",
2537 "layout");
2538 return;
2539 }
2540
2541 if (layoutQualifier.numViews == -1)
2542 {
2543 error(typeQualifier.line, "No num_views specified", "layout");
2544 return;
2545 }
2546
2547 if (layoutQualifier.numViews > mMaxNumViews)
2548 {
2549 error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
2550 "layout");
2551 return;
2552 }
2553
2554 mNumViews = layoutQualifier.numViews;
2555 }
Martin Radev802abe02016-08-04 17:48:32 +03002556 else
Jamie Madill1566ef72013-06-20 11:55:54 -04002557 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00002558 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03002559 {
Martin Radev802abe02016-08-04 17:48:32 +03002560 return;
2561 }
2562
2563 if (typeQualifier.qualifier != EvqUniform)
2564 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002565 error(typeQualifier.line, "invalid qualifier: global layout must be uniform",
2566 getQualifierString(typeQualifier.qualifier));
Martin Radev802abe02016-08-04 17:48:32 +03002567 return;
2568 }
2569
2570 if (mShaderVersion < 300)
2571 {
2572 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
2573 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002574 return;
2575 }
2576
Olli Etuaho09b04a22016-12-15 13:30:26 +00002577 checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002578
2579 if (layoutQualifier.matrixPacking != EmpUnspecified)
2580 {
2581 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
2582 }
2583
2584 if (layoutQualifier.blockStorage != EbsUnspecified)
2585 {
2586 mDefaultBlockStorage = layoutQualifier.blockStorage;
2587 }
Jamie Madill1566ef72013-06-20 11:55:54 -04002588 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002589}
2590
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002591TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
2592 const TFunction &function,
2593 const TSourceLoc &location,
2594 bool insertParametersToSymbolTable)
2595{
Olli Etuahofe486322017-03-21 09:30:54 +00002596 TIntermFunctionPrototype *prototype =
2597 new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function));
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002598 // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
2599 // point to the data that already exists in the symbol table.
2600 prototype->getFunctionSymbolInfo()->setFromFunction(function);
2601 prototype->setLine(location);
2602
2603 for (size_t i = 0; i < function.getParamCount(); i++)
2604 {
2605 const TConstParameter &param = function.getParam(i);
2606
2607 // If the parameter has no name, it's not an error, just don't add it to symbol table (could
2608 // be used for unused args).
2609 if (param.name != nullptr)
2610 {
2611 TVariable *variable = new TVariable(param.name, *param.type);
2612
2613 // Insert the parameter in the symbol table.
2614 if (insertParametersToSymbolTable && !symbolTable.declare(variable))
2615 {
2616 error(location, "redefinition", variable->getName().c_str());
2617 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2618 continue;
2619 }
2620 TIntermSymbol *symbol = intermediate.addSymbol(
2621 variable->getUniqueId(), variable->getName(), variable->getType(), location);
2622 prototype->appendParameter(symbol);
2623 }
2624 else
2625 {
2626 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2627 }
2628 }
2629 return prototype;
2630}
2631
Olli Etuaho16c745a2017-01-16 17:02:27 +00002632TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
2633 const TFunction &parsedFunction,
2634 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002635{
Olli Etuaho476197f2016-10-11 13:59:08 +01002636 // Note: function found from the symbol table could be the same as parsedFunction if this is the
2637 // first declaration. Either way the instance in the symbol table is used to track whether the
2638 // function is declared multiple times.
2639 TFunction *function = static_cast<TFunction *>(
2640 symbolTable.find(parsedFunction.getMangledName(), getShaderVersion()));
2641 if (function->hasPrototypeDeclaration() && mShaderVersion == 100)
Olli Etuaho5d653182016-01-04 14:43:28 +02002642 {
2643 // ESSL 1.00.17 section 4.2.7.
2644 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
2645 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02002646 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002647 function->setHasPrototypeDeclaration();
Olli Etuaho5d653182016-01-04 14:43:28 +02002648
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002649 TIntermFunctionPrototype *prototype =
2650 createPrototypeNodeFromFunction(*function, location, false);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002651
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002652 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002653
2654 if (!symbolTable.atGlobalLevel())
2655 {
2656 // ESSL 3.00.4 section 4.2.4.
2657 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002658 }
2659
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002660 return prototype;
2661}
2662
Olli Etuaho336b1472016-10-05 16:37:55 +01002663TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002664 TIntermFunctionPrototype *functionPrototype,
Olli Etuaho336b1472016-10-05 16:37:55 +01002665 TIntermBlock *functionBody,
2666 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002667{
Olli Etuahof51fdd22016-10-03 10:03:40 +01002668 // Check that non-void functions have at least one return statement.
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002669 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2670 {
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002671 error(location, "function does not return a value:",
2672 functionPrototype->getFunctionSymbolInfo()->getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002673 }
2674
Olli Etuahof51fdd22016-10-03 10:03:40 +01002675 if (functionBody == nullptr)
2676 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01002677 functionBody = new TIntermBlock();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002678 functionBody->setLine(location);
2679 }
Olli Etuaho336b1472016-10-05 16:37:55 +01002680 TIntermFunctionDefinition *functionNode =
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002681 new TIntermFunctionDefinition(functionPrototype, functionBody);
Olli Etuaho336b1472016-10-05 16:37:55 +01002682 functionNode->setLine(location);
Olli Etuahof51fdd22016-10-03 10:03:40 +01002683
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002684 symbolTable.pop();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002685 return functionNode;
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002686}
2687
Olli Etuaho476197f2016-10-11 13:59:08 +01002688void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
2689 TFunction **function,
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002690 TIntermFunctionPrototype **prototypeOut)
Jamie Madill185fb402015-06-12 15:48:48 -04002691{
Olli Etuaho476197f2016-10-11 13:59:08 +01002692 ASSERT(function);
2693 ASSERT(*function);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002694 const TSymbol *builtIn =
Olli Etuaho476197f2016-10-11 13:59:08 +01002695 symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002696
2697 if (builtIn)
2698 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002699 error(location, "built-in functions cannot be redefined", (*function)->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002700 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002701 else
Jamie Madill185fb402015-06-12 15:48:48 -04002702 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002703 TFunction *prevDec = static_cast<TFunction *>(
2704 symbolTable.find((*function)->getMangledName(), getShaderVersion()));
2705
2706 // Note: 'prevDec' could be 'function' if this is the first time we've seen function as it
2707 // would have just been put in the symbol table. Otherwise, we're looking up an earlier
2708 // occurance.
2709 if (*function != prevDec)
2710 {
2711 // Swap the parameters of the previous declaration to the parameters of the function
2712 // definition (parameter names may differ).
2713 prevDec->swapParameters(**function);
2714
2715 // The function definition will share the same symbol as any previous declaration.
2716 *function = prevDec;
2717 }
2718
2719 if ((*function)->isDefined())
2720 {
2721 error(location, "function already has a body", (*function)->getName().c_str());
2722 }
2723
2724 (*function)->setDefined();
Jamie Madill185fb402015-06-12 15:48:48 -04002725 }
Jamie Madill185fb402015-06-12 15:48:48 -04002726
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002727 // Remember the return type for later checking for return statements.
Olli Etuaho476197f2016-10-11 13:59:08 +01002728 mCurrentFunctionType = &((*function)->getReturnType());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002729 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002730
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002731 *prototypeOut = createPrototypeNodeFromFunction(**function, location, true);
Jamie Madill185fb402015-06-12 15:48:48 -04002732 setLoopNestingLevel(0);
2733}
2734
Jamie Madillb98c3a82015-07-23 14:26:04 -04002735TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002736{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002737 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002738 // We don't know at this point whether this is a function definition or a prototype.
2739 // The definition production code will check for redefinitions.
2740 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002741 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002742 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2743 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002744 //
2745 TFunction *prevDec =
2746 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302747
Martin Radevda6254b2016-12-14 17:00:36 +02002748 if (getShaderVersion() >= 300 &&
2749 symbolTable.hasUnmangledBuiltInForShaderVersion(function->getName().c_str(),
2750 getShaderVersion()))
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302751 {
Martin Radevda6254b2016-12-14 17:00:36 +02002752 // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions.
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302753 // Therefore overloading or redefining builtin functions is an error.
2754 error(location, "Name of a built-in function cannot be redeclared as function",
2755 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302756 }
2757 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002758 {
2759 if (prevDec->getReturnType() != function->getReturnType())
2760 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002761 error(location, "function must have the same return type in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002762 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002763 }
2764 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2765 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002766 if (prevDec->getParam(i).type->getQualifier() !=
2767 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002768 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002769 error(location,
2770 "function must have the same parameter qualifiers in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002771 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002772 }
2773 }
2774 }
2775
2776 //
2777 // Check for previously declared variables using the same name.
2778 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002779 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002780 if (prevSym)
2781 {
2782 if (!prevSym->isFunction())
2783 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002784 error(location, "redefinition of a function", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002785 }
2786 }
2787 else
2788 {
2789 // Insert the unmangled name to detect potential future redefinition as a variable.
Olli Etuaho476197f2016-10-11 13:59:08 +01002790 symbolTable.getOuterLevel()->insertUnmangled(function);
Jamie Madill185fb402015-06-12 15:48:48 -04002791 }
2792
2793 // We're at the inner scope level of the function's arguments and body statement.
2794 // Add the function prototype to the surrounding scope instead.
2795 symbolTable.getOuterLevel()->insert(function);
2796
Olli Etuaho78d13742017-01-18 13:06:10 +00002797 // Raise error message if main function takes any parameters or return anything other than void
2798 if (function->getName() == "main")
2799 {
2800 if (function->getParamCount() > 0)
2801 {
2802 error(location, "function cannot take any parameter(s)", "main");
2803 }
2804 if (function->getReturnType().getBasicType() != EbtVoid)
2805 {
2806 error(location, "main function cannot return a value",
2807 function->getReturnType().getBasicString());
2808 }
2809 }
2810
Jamie Madill185fb402015-06-12 15:48:48 -04002811 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002812 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2813 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002814 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2815 //
2816 return function;
2817}
2818
Olli Etuaho9de84a52016-06-14 17:36:01 +03002819TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2820 const TString *name,
2821 const TSourceLoc &location)
2822{
2823 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2824 {
2825 error(location, "no qualifiers allowed for function return",
2826 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002827 }
2828 if (!type.layoutQualifier.isEmpty())
2829 {
2830 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002831 }
jchen10cc2a10e2017-05-03 14:05:12 +08002832 // make sure an opaque type is not involved as well...
2833 std::string reason(getBasicString(type.getBasicType()));
2834 reason += "s can't be function return values";
2835 checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002836 if (mShaderVersion < 300)
2837 {
2838 // Array return values are forbidden, but there's also no valid syntax for declaring array
2839 // return values in ESSL 1.00.
Olli Etuaho77ba4082016-12-16 12:01:18 +00002840 ASSERT(type.arraySize == 0 || mDiagnostics->numErrors() > 0);
Olli Etuahoe29324f2016-06-15 10:58:03 +03002841
2842 if (type.isStructureContainingArrays())
2843 {
2844 // ESSL 1.00.17 section 6.1 Function Definitions
2845 error(location, "structures containing arrays can't be function return values",
2846 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002847 }
2848 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002849
2850 // Add the function as a prototype after parsing it (we do not support recursion)
2851 return new TFunction(name, new TType(type));
2852}
2853
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002854TFunction *TParseContext::addConstructorFunc(const TPublicType &publicType)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002855{
Martin Radev4a9cd802016-09-01 16:51:51 +03002856 if (publicType.isStructSpecifier())
Olli Etuahobd163f62015-11-13 12:15:38 +02002857 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002858 error(publicType.getLine(), "constructor can't be a structure definition",
2859 getBasicString(publicType.getBasicType()));
Olli Etuahobd163f62015-11-13 12:15:38 +02002860 }
2861
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002862 TType *type = new TType(publicType);
2863 if (!type->canBeConstructed())
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002864 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002865 error(publicType.getLine(), "cannot construct this type",
2866 getBasicString(publicType.getBasicType()));
2867 type->setBasicType(EbtFloat);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002868 }
2869
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002870 return new TFunction(nullptr, type, EOpConstruct);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002871}
2872
Jamie Madillb98c3a82015-07-23 14:26:04 -04002873// This function is used to test for the correctness of the parameters passed to various constructor
2874// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002875//
Olli Etuaho856c4972016-08-08 11:38:39 +03002876// 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 +00002877//
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002878TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00002879 TType type,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302880 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002881{
Olli Etuaho856c4972016-08-08 11:38:39 +03002882 if (type.isUnsizedArray())
2883 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002884 if (arguments->empty())
Olli Etuahobbe9fb52016-11-03 17:16:05 +00002885 {
2886 error(line, "implicitly sized array constructor must have at least one argument", "[]");
2887 type.setArraySize(1u);
2888 return TIntermTyped::CreateZero(type);
2889 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002890 type.setArraySize(static_cast<unsigned int>(arguments->size()));
Olli Etuaho856c4972016-08-08 11:38:39 +03002891 }
Olli Etuaho856c4972016-08-08 11:38:39 +03002892
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002893 if (!checkConstructorArguments(line, arguments, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002894 {
Olli Etuaho72d10202017-01-19 15:58:30 +00002895 return TIntermTyped::CreateZero(type);
Olli Etuaho856c4972016-08-08 11:38:39 +03002896 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002897
Olli Etuahoa7ecec32017-05-08 17:43:55 +03002898 TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002899 constructorNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002900
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002901 TIntermTyped *constConstructor =
2902 intermediate.foldAggregateBuiltIn(constructorNode, mDiagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002903 if (constConstructor)
2904 {
2905 return constConstructor;
2906 }
2907
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002908 return constructorNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002909}
2910
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002911//
2912// Interface/uniform blocks
2913//
Olli Etuaho13389b62016-10-16 11:48:18 +01002914TIntermDeclaration *TParseContext::addInterfaceBlock(
Martin Radev70866b82016-07-22 15:27:42 +03002915 const TTypeQualifierBuilder &typeQualifierBuilder,
2916 const TSourceLoc &nameLine,
2917 const TString &blockName,
2918 TFieldList *fieldList,
2919 const TString *instanceName,
2920 const TSourceLoc &instanceLine,
2921 TIntermTyped *arrayIndex,
2922 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002923{
Olli Etuaho856c4972016-08-08 11:38:39 +03002924 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002925
Olli Etuaho77ba4082016-12-16 12:01:18 +00002926 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03002927
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002928 if (typeQualifier.qualifier != EvqUniform)
2929 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002930 error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform",
2931 getQualifierString(typeQualifier.qualifier));
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002932 }
2933
Martin Radev70866b82016-07-22 15:27:42 +03002934 if (typeQualifier.invariant)
2935 {
2936 error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
2937 }
2938
Olli Etuaho43364892017-02-13 16:00:12 +00002939 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
2940
jchen10af713a22017-04-19 09:10:56 +08002941 // add array index
2942 unsigned int arraySize = 0;
2943 if (arrayIndex != nullptr)
2944 {
2945 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
2946 }
2947
2948 if (mShaderVersion < 310)
2949 {
2950 checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
2951 }
2952 else
2953 {
2954 checkBlockBindingIsValid(typeQualifier.line, typeQualifier.layoutQualifier.binding,
2955 arraySize);
2956 }
Martin Radev2cc85b32016-08-05 16:22:53 +03002957
Andrei Volykhina5527072017-03-22 16:46:30 +03002958 checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
2959
Jamie Madill099c0f32013-06-20 11:55:52 -04002960 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03002961 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04002962
Jamie Madill099c0f32013-06-20 11:55:52 -04002963 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2964 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002965 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002966 }
2967
Jamie Madill1566ef72013-06-20 11:55:54 -04002968 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2969 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002970 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002971 }
2972
Olli Etuaho856c4972016-08-08 11:38:39 +03002973 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002974
Martin Radev2cc85b32016-08-05 16:22:53 +03002975 checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
2976
Arun Patole7e7e68d2015-05-22 12:02:25 +05302977 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2978 if (!symbolTable.declare(blockNameSymbol))
2979 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002980 error(nameLine, "redefinition of an interface block name", blockName.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002981 }
2982
Jamie Madill98493dd2013-07-08 14:39:03 -04002983 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302984 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2985 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002986 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302987 TType *fieldType = field->type();
jchen10cc2a10e2017-05-03 14:05:12 +08002988 if (IsOpaqueType(fieldType->getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +05302989 {
jchen10cc2a10e2017-05-03 14:05:12 +08002990 std::string reason("unsupported type - ");
2991 reason += fieldType->getBasicString();
2992 reason += " types are not allowed in interface blocks";
2993 error(field->line(), reason.c_str(), fieldType->getBasicString());
Martin Radev2cc85b32016-08-05 16:22:53 +03002994 }
2995
Jamie Madill98493dd2013-07-08 14:39:03 -04002996 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002997 switch (qualifier)
2998 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002999 case EvqGlobal:
3000 case EvqUniform:
3001 break;
3002 default:
3003 error(field->line(), "invalid qualifier on interface block member",
3004 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003005 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003006 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003007
Martin Radev70866b82016-07-22 15:27:42 +03003008 if (fieldType->isInvariant())
3009 {
3010 error(field->line(), "invalid qualifier on interface block member", "invariant");
3011 }
3012
Jamie Madilla5efff92013-06-06 11:56:47 -04003013 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04003014 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03003015 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
jchen10af713a22017-04-19 09:10:56 +08003016 checkBindingIsNotSpecified(field->line(), fieldLayoutQualifier.binding);
Jamie Madill099c0f32013-06-20 11:55:52 -04003017
Jamie Madill98493dd2013-07-08 14:39:03 -04003018 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04003019 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003020 error(field->line(), "invalid layout qualifier: cannot be used here",
3021 getBlockStorageString(fieldLayoutQualifier.blockStorage));
Jamie Madill1566ef72013-06-20 11:55:54 -04003022 }
3023
Jamie Madill98493dd2013-07-08 14:39:03 -04003024 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04003025 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003026 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04003027 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03003028 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04003029 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003030 warning(field->line(),
3031 "extraneous layout qualifier: only has an effect on matrix types",
3032 getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
Jamie Madill099c0f32013-06-20 11:55:52 -04003033 }
3034
Jamie Madill98493dd2013-07-08 14:39:03 -04003035 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003036 }
3037
Jamie Madillb98c3a82015-07-23 14:26:04 -04003038 TInterfaceBlock *interfaceBlock =
3039 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
3040 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
3041 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003042
3043 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04003044 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003045
Jamie Madill98493dd2013-07-08 14:39:03 -04003046 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003047 {
3048 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04003049 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
3050 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003051 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05303052 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04003053
3054 // set parent pointer of the field variable
3055 fieldType->setInterfaceBlock(interfaceBlock);
3056
Arun Patole7e7e68d2015-05-22 12:02:25 +05303057 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04003058 fieldVariable->setQualifier(typeQualifier.qualifier);
3059
Arun Patole7e7e68d2015-05-22 12:02:25 +05303060 if (!symbolTable.declare(fieldVariable))
3061 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003062 error(field->line(), "redefinition of an interface block member name",
3063 field->name().c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003064 }
3065 }
3066 }
3067 else
3068 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003069 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03003070
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003071 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05303072 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003073 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04003074
Arun Patole7e7e68d2015-05-22 12:02:25 +05303075 if (!symbolTable.declare(instanceTypeDef))
3076 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003077 error(instanceLine, "redefinition of an interface block instance name",
3078 instanceName->c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003079 }
3080
Jamie Madillb98c3a82015-07-23 14:26:04 -04003081 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003082 symbolName = instanceTypeDef->getName();
3083 }
3084
Olli Etuaho13389b62016-10-16 11:48:18 +01003085 TIntermSymbol *blockSymbol =
3086 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line);
3087 TIntermDeclaration *declaration = new TIntermDeclaration();
3088 declaration->appendDeclarator(blockSymbol);
3089 declaration->setLine(nameLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04003090
3091 exitStructDeclaration();
Olli Etuaho13389b62016-10-16 11:48:18 +01003092 return declaration;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003093}
3094
Olli Etuaho383b7912016-08-05 11:22:59 +03003095void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00003096{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003097 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003098
3099 // Embedded structure definitions are not supported per GLSL ES spec.
Olli Etuaho4de340a2016-12-16 09:32:03 +00003100 // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
Arun Patole7e7e68d2015-05-22 12:02:25 +05303101 if (mStructNestingLevel > 1)
3102 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003103 error(line, "Embedded struct definitions are not allowed", "struct");
kbr@chromium.org476541f2011-10-27 21:14:51 +00003104 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00003105}
3106
3107void TParseContext::exitStructDeclaration()
3108{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003109 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003110}
3111
Olli Etuaho8a176262016-08-16 14:23:01 +03003112void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00003113{
Jamie Madillacb4b812016-11-07 13:50:29 -05003114 if (!sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +05303115 {
Olli Etuaho8a176262016-08-16 14:23:01 +03003116 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003117 }
3118
Arun Patole7e7e68d2015-05-22 12:02:25 +05303119 if (field.type()->getBasicType() != EbtStruct)
3120 {
Olli Etuaho8a176262016-08-16 14:23:01 +03003121 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003122 }
3123
3124 // We're already inside a structure definition at this point, so add
3125 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05303126 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
3127 {
Jamie Madill41a49272014-03-18 16:10:13 -04003128 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003129 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
3130 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04003131 std::string reason = reasonStream.str();
Olli Etuaho4de340a2016-12-16 09:32:03 +00003132 error(line, reason.c_str(), field.name().c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03003133 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003134 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00003135}
3136
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003137//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003138// Parse an array index expression
3139//
Jamie Madillb98c3a82015-07-23 14:26:04 -04003140TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
3141 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303142 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003143{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003144 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
3145 {
3146 if (baseExpression->getAsSymbolNode())
3147 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303148 error(location, " left of '[' is not of type array, matrix, or vector ",
3149 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003150 }
3151 else
3152 {
3153 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
3154 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003155
3156 TConstantUnion *unionArray = new TConstantUnion[1];
3157 unionArray->setFConst(0.0f);
3158 return intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst),
3159 location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003160 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003161
Jamie Madill21c1e452014-12-29 11:33:41 -05003162 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
3163
Olli Etuaho36b05142015-11-12 13:10:42 +02003164 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
3165 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
3166 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
3167 // index is a constant expression.
3168 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
3169 {
3170 if (baseExpression->isInterfaceBlock())
3171 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003172 error(location,
3173 "array indexes for interface blocks arrays must be constant integral expressions",
3174 "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02003175 }
3176 else if (baseExpression->getQualifier() == EvqFragmentOut)
3177 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003178 error(location,
3179 "array indexes for fragment outputs must be constant integral expressions", "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02003180 }
Olli Etuaho3e960462015-11-12 15:58:39 +02003181 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
3182 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003183 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3e960462015-11-12 15:58:39 +02003184 }
Olli Etuaho36b05142015-11-12 13:10:42 +02003185 }
3186
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003187 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04003188 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003189 // If an out-of-range index is not qualified as constant, the behavior in the spec is
3190 // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
3191 // constant fold expressions that are not constant expressions). The most compatible way to
3192 // handle this case is to report a warning instead of an error and force the index to be in
3193 // the correct range.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003194 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003195 int index = indexConstantUnion->getIConst(0);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003196
3197 int safeIndex = -1;
3198
3199 if (baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04003200 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003201 if (baseExpression->getQualifier() == EvqFragData && index > 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003202 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003203 if (mShaderSpec == SH_WEBGL2_SPEC)
3204 {
3205 // Error has been already generated if index is not const.
3206 if (indexExpression->getQualifier() == EvqConst)
3207 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003208 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003209 }
3210 safeIndex = 0;
3211 }
3212 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
3213 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003214 outOfRangeError(outOfRangeIndexIsError, location,
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003215 "array index for gl_FragData must be zero when "
Olli Etuaho4de340a2016-12-16 09:32:03 +00003216 "GL_EXT_draw_buffers is disabled",
3217 "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003218 safeIndex = 0;
3219 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03003220 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003221 // Only do generic out-of-range check if similar error hasn't already been reported.
3222 if (safeIndex < 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003223 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003224 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3225 baseExpression->getArraySize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003226 "array index out of range");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003227 }
3228 }
3229 else if (baseExpression->isMatrix())
3230 {
3231 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
Olli Etuaho90892fb2016-07-14 14:44:51 +03003232 baseExpression->getType().getCols(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003233 "matrix field selection out of range");
Jamie Madill7164cf42013-07-08 13:30:59 -04003234 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003235 else if (baseExpression->isVector())
Jamie Madill7164cf42013-07-08 13:30:59 -04003236 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003237 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3238 baseExpression->getType().getNominalSize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003239 "vector field selection out of range");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003240 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003241
3242 ASSERT(safeIndex >= 0);
3243 // Data of constant unions can't be changed, because it may be shared with other
3244 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
3245 // sanitized object.
3246 if (safeIndex != index)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003247 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003248 TConstantUnion *safeConstantUnion = new TConstantUnion();
3249 safeConstantUnion->setIConst(safeIndex);
3250 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003251 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003252
3253 return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003254 mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003255 }
Jamie Madill7164cf42013-07-08 13:30:59 -04003256 else
3257 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003258 return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003259 mDiagnostics);
Jamie Madill7164cf42013-07-08 13:30:59 -04003260 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003261}
3262
Olli Etuaho90892fb2016-07-14 14:44:51 +03003263int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
3264 const TSourceLoc &location,
3265 int index,
3266 int arraySize,
Olli Etuaho4de340a2016-12-16 09:32:03 +00003267 const char *reason)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003268{
3269 if (index >= arraySize || index < 0)
3270 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003271 std::stringstream reasonStream;
3272 reasonStream << reason << " '" << index << "'";
3273 std::string token = reasonStream.str();
3274 outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
Olli Etuaho90892fb2016-07-14 14:44:51 +03003275 if (index < 0)
3276 {
3277 return 0;
3278 }
3279 else
3280 {
3281 return arraySize - 1;
3282 }
3283 }
3284 return index;
3285}
3286
Jamie Madillb98c3a82015-07-23 14:26:04 -04003287TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
3288 const TSourceLoc &dotLocation,
3289 const TString &fieldString,
3290 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003291{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003292 if (baseExpression->isArray())
3293 {
3294 error(fieldLocation, "cannot apply dot operator to an array", ".");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003295 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003296 }
3297
3298 if (baseExpression->isVector())
3299 {
3300 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003301 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
3302 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003303 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003304 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003305 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003306 }
3307
Olli Etuahob6fa0432016-09-28 16:28:05 +01003308 return TIntermediate::AddSwizzle(baseExpression, fields, dotLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003309 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003310 else if (baseExpression->getBasicType() == EbtStruct)
3311 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303312 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003313 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003314 {
3315 error(dotLocation, "structure has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003316 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003317 }
3318 else
3319 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003320 bool fieldFound = false;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003321 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003322 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003323 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003324 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003325 {
3326 fieldFound = true;
3327 break;
3328 }
3329 }
3330 if (fieldFound)
3331 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003332 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3333 index->setLine(fieldLocation);
3334 return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003335 dotLocation, mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003336 }
3337 else
3338 {
3339 error(dotLocation, " no such field in structure", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003340 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003341 }
3342 }
3343 }
Jamie Madill98493dd2013-07-08 14:39:03 -04003344 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003345 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303346 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003347 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003348 {
3349 error(dotLocation, "interface block has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003350 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003351 }
3352 else
3353 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003354 bool fieldFound = false;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003355 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003356 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003357 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003358 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003359 {
3360 fieldFound = true;
3361 break;
3362 }
3363 }
3364 if (fieldFound)
3365 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003366 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3367 index->setLine(fieldLocation);
3368 return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003369 dotLocation, mDiagnostics);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003370 }
3371 else
3372 {
3373 error(dotLocation, " no such field in interface block", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003374 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003375 }
3376 }
3377 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003378 else
3379 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003380 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003381 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03003382 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303383 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003384 }
3385 else
3386 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303387 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03003388 " field selection requires structure, vector, or interface block on left hand "
3389 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303390 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003391 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003392 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003393 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003394}
3395
Jamie Madillb98c3a82015-07-23 14:26:04 -04003396TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3397 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003398{
Martin Radev802abe02016-08-04 17:48:32 +03003399 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003400
3401 if (qualifierType == "shared")
3402 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003403 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003404 {
3405 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
3406 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003407 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003408 }
3409 else if (qualifierType == "packed")
3410 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003411 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003412 {
3413 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
3414 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003415 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003416 }
3417 else if (qualifierType == "std140")
3418 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003419 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003420 }
3421 else if (qualifierType == "row_major")
3422 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003423 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003424 }
3425 else if (qualifierType == "column_major")
3426 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003427 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003428 }
3429 else if (qualifierType == "location")
3430 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003431 error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
3432 qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003433 }
Andrei Volykhina5527072017-03-22 16:46:30 +03003434 else if (qualifierType == "yuv" && isExtensionEnabled("GL_EXT_YUV_target") &&
3435 mShaderType == GL_FRAGMENT_SHADER)
3436 {
3437 qualifier.yuv = true;
3438 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003439 else if (qualifierType == "rgba32f")
3440 {
3441 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3442 qualifier.imageInternalFormat = EiifRGBA32F;
3443 }
3444 else if (qualifierType == "rgba16f")
3445 {
3446 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3447 qualifier.imageInternalFormat = EiifRGBA16F;
3448 }
3449 else if (qualifierType == "r32f")
3450 {
3451 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3452 qualifier.imageInternalFormat = EiifR32F;
3453 }
3454 else if (qualifierType == "rgba8")
3455 {
3456 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3457 qualifier.imageInternalFormat = EiifRGBA8;
3458 }
3459 else if (qualifierType == "rgba8_snorm")
3460 {
3461 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3462 qualifier.imageInternalFormat = EiifRGBA8_SNORM;
3463 }
3464 else if (qualifierType == "rgba32i")
3465 {
3466 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3467 qualifier.imageInternalFormat = EiifRGBA32I;
3468 }
3469 else if (qualifierType == "rgba16i")
3470 {
3471 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3472 qualifier.imageInternalFormat = EiifRGBA16I;
3473 }
3474 else if (qualifierType == "rgba8i")
3475 {
3476 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3477 qualifier.imageInternalFormat = EiifRGBA8I;
3478 }
3479 else if (qualifierType == "r32i")
3480 {
3481 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3482 qualifier.imageInternalFormat = EiifR32I;
3483 }
3484 else if (qualifierType == "rgba32ui")
3485 {
3486 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3487 qualifier.imageInternalFormat = EiifRGBA32UI;
3488 }
3489 else if (qualifierType == "rgba16ui")
3490 {
3491 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3492 qualifier.imageInternalFormat = EiifRGBA16UI;
3493 }
3494 else if (qualifierType == "rgba8ui")
3495 {
3496 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3497 qualifier.imageInternalFormat = EiifRGBA8UI;
3498 }
3499 else if (qualifierType == "r32ui")
3500 {
3501 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3502 qualifier.imageInternalFormat = EiifR32UI;
3503 }
3504
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003505 else
3506 {
3507 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003508 }
3509
Jamie Madilla5efff92013-06-06 11:56:47 -04003510 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003511}
3512
Martin Radev802abe02016-08-04 17:48:32 +03003513void TParseContext::parseLocalSize(const TString &qualifierType,
3514 const TSourceLoc &qualifierTypeLine,
3515 int intValue,
3516 const TSourceLoc &intValueLine,
3517 const std::string &intValueString,
3518 size_t index,
Martin Radev4c4c8e72016-08-04 12:25:34 +03003519 sh::WorkGroupSize *localSize)
Martin Radev802abe02016-08-04 17:48:32 +03003520{
Olli Etuaho856c4972016-08-08 11:38:39 +03003521 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03003522 if (intValue < 1)
3523 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003524 std::stringstream reasonStream;
3525 reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
3526 std::string reason = reasonStream.str();
3527 error(intValueLine, reason.c_str(), intValueString.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003528 }
3529 (*localSize)[index] = intValue;
3530}
3531
Olli Etuaho09b04a22016-12-15 13:30:26 +00003532void TParseContext::parseNumViews(int intValue,
3533 const TSourceLoc &intValueLine,
3534 const std::string &intValueString,
3535 int *numViews)
3536{
3537 // This error is only specified in WebGL, but tightens unspecified behavior in the native
3538 // specification.
3539 if (intValue < 1)
3540 {
3541 error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
3542 }
3543 *numViews = intValue;
3544}
3545
Jamie Madillb98c3a82015-07-23 14:26:04 -04003546TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3547 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003548 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303549 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003550{
Martin Radev802abe02016-08-04 17:48:32 +03003551 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003552
Martin Radev802abe02016-08-04 17:48:32 +03003553 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003554
Martin Radev802abe02016-08-04 17:48:32 +03003555 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003556 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003557 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003558 if (intValue < 0)
3559 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003560 error(intValueLine, "out of range: location must be non-negative",
3561 intValueString.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003562 }
3563 else
3564 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003565 qualifier.location = intValue;
Olli Etuaho87d410c2016-09-05 13:33:26 +03003566 qualifier.locationsSpecified = 1;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003567 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003568 }
Olli Etuaho43364892017-02-13 16:00:12 +00003569 else if (qualifierType == "binding")
3570 {
3571 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3572 if (intValue < 0)
3573 {
3574 error(intValueLine, "out of range: binding must be non-negative",
3575 intValueString.c_str());
3576 }
3577 else
3578 {
3579 qualifier.binding = intValue;
3580 }
3581 }
jchen104cdac9e2017-05-08 11:01:20 +08003582 else if (qualifierType == "offset")
3583 {
3584 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3585 if (intValue < 0)
3586 {
3587 error(intValueLine, "out of range: offset must be non-negative",
3588 intValueString.c_str());
3589 }
3590 else
3591 {
3592 qualifier.offset = intValue;
3593 }
3594 }
Martin Radev802abe02016-08-04 17:48:32 +03003595 else if (qualifierType == "local_size_x")
3596 {
3597 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3598 &qualifier.localSize);
3599 }
3600 else if (qualifierType == "local_size_y")
3601 {
3602 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3603 &qualifier.localSize);
3604 }
3605 else if (qualifierType == "local_size_z")
3606 {
3607 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3608 &qualifier.localSize);
3609 }
Olli Etuaho95468d12017-05-04 11:14:34 +03003610 else if (qualifierType == "num_views" && isMultiviewExtensionEnabled() &&
Olli Etuaho09b04a22016-12-15 13:30:26 +00003611 mShaderType == GL_VERTEX_SHADER)
3612 {
3613 parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
3614 }
Martin Radev802abe02016-08-04 17:48:32 +03003615 else
3616 {
3617 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003618 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003619
Jamie Madilla5efff92013-06-06 11:56:47 -04003620 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003621}
3622
Olli Etuaho613b9592016-09-05 12:05:53 +03003623TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
3624{
3625 return new TTypeQualifierBuilder(
3626 new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
3627 mShaderVersion);
3628}
3629
Jamie Madillb98c3a82015-07-23 14:26:04 -04003630TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003631 TLayoutQualifier rightQualifier,
3632 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003633{
Martin Radevc28888b2016-07-22 15:27:42 +03003634 return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003635 mDiagnostics);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003636}
3637
Olli Etuaho4de340a2016-12-16 09:32:03 +00003638TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
3639 const TFieldList *newlyAddedFields,
3640 const TSourceLoc &location)
3641{
3642 for (TField *field : *newlyAddedFields)
3643 {
3644 for (TField *oldField : *processedFields)
3645 {
3646 if (oldField->name() == field->name())
3647 {
3648 error(location, "duplicate field name in structure", field->name().c_str());
3649 }
3650 }
3651 processedFields->push_back(field);
3652 }
3653 return processedFields;
3654}
3655
Martin Radev70866b82016-07-22 15:27:42 +03003656TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
3657 const TTypeQualifierBuilder &typeQualifierBuilder,
3658 TPublicType *typeSpecifier,
3659 TFieldList *fieldList)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003660{
Olli Etuaho77ba4082016-12-16 12:01:18 +00003661 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003662
Martin Radev70866b82016-07-22 15:27:42 +03003663 typeSpecifier->qualifier = typeQualifier.qualifier;
3664 typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03003665 typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03003666 typeSpecifier->invariant = typeQualifier.invariant;
3667 if (typeQualifier.precision != EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +05303668 {
Martin Radev70866b82016-07-22 15:27:42 +03003669 typeSpecifier->precision = typeQualifier.precision;
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003670 }
Martin Radev70866b82016-07-22 15:27:42 +03003671 return addStructDeclaratorList(*typeSpecifier, fieldList);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003672}
3673
Jamie Madillb98c3a82015-07-23 14:26:04 -04003674TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3675 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003676{
Martin Radev4a9cd802016-09-01 16:51:51 +03003677 checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
3678 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03003679
Martin Radev4a9cd802016-09-01 16:51:51 +03003680 checkIsNonVoid(typeSpecifier.getLine(), (*fieldList)[0]->name(), typeSpecifier.getBasicType());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003681
Martin Radev4a9cd802016-09-01 16:51:51 +03003682 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003683
Arun Patole7e7e68d2015-05-22 12:02:25 +05303684 for (unsigned int i = 0; i < fieldList->size(); ++i)
3685 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003686 //
3687 // Careful not to replace already known aspects of type, like array-ness
3688 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303689 TType *type = (*fieldList)[i]->type();
Martin Radev4a9cd802016-09-01 16:51:51 +03003690 type->setBasicType(typeSpecifier.getBasicType());
3691 type->setPrimarySize(typeSpecifier.getPrimarySize());
3692 type->setSecondarySize(typeSpecifier.getSecondarySize());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003693 type->setPrecision(typeSpecifier.precision);
3694 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003695 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
Martin Radev2cc85b32016-08-05 16:22:53 +03003696 type->setMemoryQualifier(typeSpecifier.memoryQualifier);
Martin Radev70866b82016-07-22 15:27:42 +03003697 type->setInvariant(typeSpecifier.invariant);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003698
3699 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303700 if (type->isArray())
3701 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003702 checkIsValidTypeForArray(typeSpecifier.getLine(), typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003703 }
3704 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003705 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Martin Radev4a9cd802016-09-01 16:51:51 +03003706 if (typeSpecifier.getUserDef())
Arun Patole7e7e68d2015-05-22 12:02:25 +05303707 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003708 type->setStruct(typeSpecifier.getUserDef()->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003709 }
3710
Martin Radev4a9cd802016-09-01 16:51:51 +03003711 checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003712 }
3713
Jamie Madill98493dd2013-07-08 14:39:03 -04003714 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003715}
3716
Martin Radev4a9cd802016-09-01 16:51:51 +03003717TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
3718 const TSourceLoc &nameLine,
3719 const TString *structName,
3720 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003721{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303722 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003723 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003724
Jamie Madill9b820842015-02-12 10:40:10 -05003725 // Store a bool in the struct if we're at global scope, to allow us to
3726 // skip the local struct scoping workaround in HLSL.
Jamie Madill9b820842015-02-12 10:40:10 -05003727 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003728
Jamie Madill98493dd2013-07-08 14:39:03 -04003729 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003730 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003731 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303732 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3733 if (!symbolTable.declare(userTypeDef))
3734 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003735 error(nameLine, "redefinition of a struct", structName->c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003736 }
3737 }
3738
3739 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003740 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003741 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003742 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003743 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003744 switch (qualifier)
3745 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003746 case EvqGlobal:
3747 case EvqTemporary:
3748 break;
3749 default:
3750 error(field.line(), "invalid qualifier on struct member",
3751 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003752 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003753 }
Martin Radev70866b82016-07-22 15:27:42 +03003754 if (field.type()->isInvariant())
3755 {
3756 error(field.line(), "invalid qualifier on struct member", "invariant");
3757 }
jchen104cdac9e2017-05-08 11:01:20 +08003758 // ESSL 3.10 section 4.1.8 -- atomic_uint or images are not allowed as structure member.
3759 if (IsImage(field.type()->getBasicType()) || IsAtomicCounter(field.type()->getBasicType()))
Martin Radev2cc85b32016-08-05 16:22:53 +03003760 {
3761 error(field.line(), "disallowed type in struct", field.type()->getBasicString());
3762 }
3763
Olli Etuaho43364892017-02-13 16:00:12 +00003764 checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
3765
3766 checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);
Martin Radev70866b82016-07-22 15:27:42 +03003767
3768 checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003769 }
3770
Martin Radev4a9cd802016-09-01 16:51:51 +03003771 TTypeSpecifierNonArray typeSpecifierNonArray;
3772 typeSpecifierNonArray.initialize(EbtStruct, structLine);
3773 typeSpecifierNonArray.userDef = structureType;
3774 typeSpecifierNonArray.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003775 exitStructDeclaration();
3776
Martin Radev4a9cd802016-09-01 16:51:51 +03003777 return typeSpecifierNonArray;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003778}
3779
Jamie Madillb98c3a82015-07-23 14:26:04 -04003780TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01003781 TIntermBlock *statementList,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003782 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003783{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003784 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003785 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003786 init->isVector())
3787 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003788 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3789 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003790 return nullptr;
3791 }
3792
Olli Etuahoac5274d2015-02-20 10:19:08 +02003793 if (statementList)
3794 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00003795 if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
Olli Etuahoac5274d2015-02-20 10:19:08 +02003796 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003797 return nullptr;
3798 }
3799 }
3800
Olli Etuahoa3a36662015-02-17 13:46:51 +02003801 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3802 if (node == nullptr)
3803 {
3804 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003805 return nullptr;
3806 }
3807 return node;
3808}
3809
3810TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3811{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003812 if (mSwitchNestingLevel == 0)
3813 {
3814 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003815 return nullptr;
3816 }
3817 if (condition == nullptr)
3818 {
3819 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003820 return nullptr;
3821 }
3822 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003823 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003824 {
3825 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003826 }
3827 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003828 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3829 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3830 // fold in case labels.
3831 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003832 {
3833 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003834 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003835 TIntermCase *node = intermediate.addCase(condition, loc);
3836 if (node == nullptr)
3837 {
3838 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003839 return nullptr;
3840 }
3841 return node;
3842}
3843
3844TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3845{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003846 if (mSwitchNestingLevel == 0)
3847 {
3848 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003849 return nullptr;
3850 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003851 TIntermCase *node = intermediate.addCase(nullptr, loc);
3852 if (node == nullptr)
3853 {
3854 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003855 return nullptr;
3856 }
3857 return node;
3858}
3859
Jamie Madillb98c3a82015-07-23 14:26:04 -04003860TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3861 TIntermTyped *child,
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003862 const TSourceLoc &loc)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003863{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003864 ASSERT(child != nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003865
3866 switch (op)
3867 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003868 case EOpLogicalNot:
3869 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3870 child->isVector())
3871 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003872 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003873 return nullptr;
3874 }
3875 break;
3876 case EOpBitwiseNot:
3877 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3878 child->isMatrix() || child->isArray())
3879 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003880 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003881 return nullptr;
3882 }
3883 break;
3884 case EOpPostIncrement:
3885 case EOpPreIncrement:
3886 case EOpPostDecrement:
3887 case EOpPreDecrement:
3888 case EOpNegative:
3889 case EOpPositive:
Olli Etuaho94050052017-05-08 14:17:44 +03003890 if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() ||
3891 child->getBasicType() == EbtBool || child->isArray() ||
3892 IsOpaqueType(child->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -04003893 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003894 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003895 return nullptr;
3896 }
3897 // Operators for built-ins are already type checked against their prototype.
3898 default:
3899 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003900 }
3901
Olli Etuahof119a262016-08-19 15:54:22 +03003902 TIntermUnary *node = new TIntermUnary(op, child);
3903 node->setLine(loc);
Olli Etuahof119a262016-08-19 15:54:22 +03003904
Olli Etuaho77ba4082016-12-16 12:01:18 +00003905 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuahof119a262016-08-19 15:54:22 +03003906 if (foldedNode)
3907 return foldedNode;
3908
3909 return node;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003910}
3911
Olli Etuaho09b22472015-02-11 11:47:26 +02003912TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3913{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003914 TIntermTyped *node = createUnaryMath(op, child, loc);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003915 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003916 {
Olli Etuaho09b22472015-02-11 11:47:26 +02003917 return child;
3918 }
3919 return node;
3920}
3921
Jamie Madillb98c3a82015-07-23 14:26:04 -04003922TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3923 TIntermTyped *child,
3924 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003925{
Olli Etuaho856c4972016-08-08 11:38:39 +03003926 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003927 return addUnaryMath(op, child, loc);
3928}
3929
Jamie Madillb98c3a82015-07-23 14:26:04 -04003930bool TParseContext::binaryOpCommonCheck(TOperator op,
3931 TIntermTyped *left,
3932 TIntermTyped *right,
3933 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003934{
jchen10b4cf5652017-05-05 18:51:17 +08003935 // Check opaque types are not allowed to be operands in expressions other than array indexing
3936 // and structure member selection.
3937 if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType()))
3938 {
3939 switch (op)
3940 {
3941 case EOpIndexDirect:
3942 case EOpIndexIndirect:
3943 break;
3944 case EOpIndexDirectStruct:
3945 UNREACHABLE();
3946
3947 default:
3948 error(loc, "Invalid operation for variables with an opaque type",
3949 GetOperatorString(op));
3950 return false;
3951 }
3952 }
jchen10cc2a10e2017-05-03 14:05:12 +08003953
Olli Etuaho244be012016-08-18 15:26:02 +03003954 if (left->getType().getStruct() || right->getType().getStruct())
3955 {
3956 switch (op)
3957 {
3958 case EOpIndexDirectStruct:
3959 ASSERT(left->getType().getStruct());
3960 break;
3961 case EOpEqual:
3962 case EOpNotEqual:
3963 case EOpAssign:
3964 case EOpInitialize:
3965 if (left->getType() != right->getType())
3966 {
3967 return false;
3968 }
3969 break;
3970 default:
3971 error(loc, "Invalid operation for structs", GetOperatorString(op));
3972 return false;
3973 }
3974 }
3975
Olli Etuaho94050052017-05-08 14:17:44 +03003976 if (left->isInterfaceBlock() || right->isInterfaceBlock())
3977 {
3978 switch (op)
3979 {
3980 case EOpIndexDirectInterfaceBlock:
3981 ASSERT(left->getType().getInterfaceBlock());
3982 break;
3983 default:
3984 error(loc, "Invalid operation for interface blocks", GetOperatorString(op));
3985 return false;
3986 }
3987 }
3988
Olli Etuahod6b14282015-03-17 14:31:35 +02003989 if (left->isArray() || right->isArray())
3990 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003991 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003992 {
3993 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3994 return false;
3995 }
3996
3997 if (left->isArray() != right->isArray())
3998 {
3999 error(loc, "array / non-array mismatch", GetOperatorString(op));
4000 return false;
4001 }
4002
4003 switch (op)
4004 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004005 case EOpEqual:
4006 case EOpNotEqual:
4007 case EOpAssign:
4008 case EOpInitialize:
4009 break;
4010 default:
4011 error(loc, "Invalid operation for arrays", GetOperatorString(op));
4012 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02004013 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03004014 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02004015 if (left->getArraySize() != right->getArraySize())
4016 {
4017 error(loc, "array size mismatch", GetOperatorString(op));
4018 return false;
4019 }
Olli Etuahod6b14282015-03-17 14:31:35 +02004020 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004021
4022 // Check ops which require integer / ivec parameters
4023 bool isBitShift = false;
4024 switch (op)
4025 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004026 case EOpBitShiftLeft:
4027 case EOpBitShiftRight:
4028 case EOpBitShiftLeftAssign:
4029 case EOpBitShiftRightAssign:
4030 // Unsigned can be bit-shifted by signed and vice versa, but we need to
4031 // check that the basic type is an integer type.
4032 isBitShift = true;
4033 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
4034 {
4035 return false;
4036 }
4037 break;
4038 case EOpBitwiseAnd:
4039 case EOpBitwiseXor:
4040 case EOpBitwiseOr:
4041 case EOpBitwiseAndAssign:
4042 case EOpBitwiseXorAssign:
4043 case EOpBitwiseOrAssign:
4044 // It is enough to check the type of only one operand, since later it
4045 // is checked that the operand types match.
4046 if (!IsInteger(left->getBasicType()))
4047 {
4048 return false;
4049 }
4050 break;
4051 default:
4052 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004053 }
4054
4055 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
4056 // So the basic type should usually match.
4057 if (!isBitShift && left->getBasicType() != right->getBasicType())
4058 {
4059 return false;
4060 }
4061
Olli Etuaho63e1ec52016-08-18 22:05:12 +03004062 // Check that:
4063 // 1. Type sizes match exactly on ops that require that.
4064 // 2. Restrictions for structs that contain arrays or samplers are respected.
4065 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
Jamie Madillb98c3a82015-07-23 14:26:04 -04004066 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004067 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004068 case EOpAssign:
4069 case EOpInitialize:
4070 case EOpEqual:
4071 case EOpNotEqual:
4072 // ESSL 1.00 sections 5.7, 5.8, 5.9
4073 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
4074 {
4075 error(loc, "undefined operation for structs containing arrays",
4076 GetOperatorString(op));
4077 return false;
4078 }
4079 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
4080 // we interpret the spec so that this extends to structs containing samplers,
4081 // similarly to ESSL 1.00 spec.
4082 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
4083 left->getType().isStructureContainingSamplers())
4084 {
4085 error(loc, "undefined operation for structs containing samplers",
4086 GetOperatorString(op));
4087 return false;
4088 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004089
Olli Etuahoe1805592017-01-02 16:41:20 +00004090 if ((left->getNominalSize() != right->getNominalSize()) ||
4091 (left->getSecondarySize() != right->getSecondarySize()))
4092 {
4093 error(loc, "dimension mismatch", GetOperatorString(op));
4094 return false;
4095 }
4096 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004097 case EOpLessThan:
4098 case EOpGreaterThan:
4099 case EOpLessThanEqual:
4100 case EOpGreaterThanEqual:
Olli Etuahoe1805592017-01-02 16:41:20 +00004101 if (!left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04004102 {
Olli Etuahoe1805592017-01-02 16:41:20 +00004103 error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
Jamie Madillb98c3a82015-07-23 14:26:04 -04004104 return false;
4105 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03004106 break;
4107 case EOpAdd:
4108 case EOpSub:
4109 case EOpDiv:
4110 case EOpIMod:
4111 case EOpBitShiftLeft:
4112 case EOpBitShiftRight:
4113 case EOpBitwiseAnd:
4114 case EOpBitwiseXor:
4115 case EOpBitwiseOr:
4116 case EOpAddAssign:
4117 case EOpSubAssign:
4118 case EOpDivAssign:
4119 case EOpIModAssign:
4120 case EOpBitShiftLeftAssign:
4121 case EOpBitShiftRightAssign:
4122 case EOpBitwiseAndAssign:
4123 case EOpBitwiseXorAssign:
4124 case EOpBitwiseOrAssign:
4125 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
4126 {
4127 return false;
4128 }
4129
4130 // Are the sizes compatible?
4131 if (left->getNominalSize() != right->getNominalSize() ||
4132 left->getSecondarySize() != right->getSecondarySize())
4133 {
4134 // If the nominal sizes of operands do not match:
4135 // One of them must be a scalar.
4136 if (!left->isScalar() && !right->isScalar())
4137 return false;
4138
4139 // In the case of compound assignment other than multiply-assign,
4140 // the right side needs to be a scalar. Otherwise a vector/matrix
4141 // would be assigned to a scalar. A scalar can't be shifted by a
4142 // vector either.
4143 if (!right->isScalar() &&
4144 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
4145 return false;
4146 }
4147 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004148 default:
4149 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004150 }
4151
Olli Etuahod6b14282015-03-17 14:31:35 +02004152 return true;
4153}
4154
Olli Etuaho1dded802016-08-18 18:13:13 +03004155bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
4156 const TType &left,
4157 const TType &right)
4158{
4159 switch (op)
4160 {
4161 case EOpMul:
4162 case EOpMulAssign:
4163 return left.getNominalSize() == right.getNominalSize() &&
4164 left.getSecondarySize() == right.getSecondarySize();
4165 case EOpVectorTimesScalar:
4166 return true;
4167 case EOpVectorTimesScalarAssign:
4168 ASSERT(!left.isMatrix() && !right.isMatrix());
4169 return left.isVector() && !right.isVector();
4170 case EOpVectorTimesMatrix:
4171 return left.getNominalSize() == right.getRows();
4172 case EOpVectorTimesMatrixAssign:
4173 ASSERT(!left.isMatrix() && right.isMatrix());
4174 return left.isVector() && left.getNominalSize() == right.getRows() &&
4175 left.getNominalSize() == right.getCols();
4176 case EOpMatrixTimesVector:
4177 return left.getCols() == right.getNominalSize();
4178 case EOpMatrixTimesScalar:
4179 return true;
4180 case EOpMatrixTimesScalarAssign:
4181 ASSERT(left.isMatrix() && !right.isMatrix());
4182 return !right.isVector();
4183 case EOpMatrixTimesMatrix:
4184 return left.getCols() == right.getRows();
4185 case EOpMatrixTimesMatrixAssign:
4186 ASSERT(left.isMatrix() && right.isMatrix());
4187 // We need to check two things:
4188 // 1. The matrix multiplication step is valid.
4189 // 2. The result will have the same number of columns as the lvalue.
4190 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
4191
4192 default:
4193 UNREACHABLE();
4194 return false;
4195 }
4196}
4197
Jamie Madillb98c3a82015-07-23 14:26:04 -04004198TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
4199 TIntermTyped *left,
4200 TIntermTyped *right,
4201 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02004202{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004203 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004204 return nullptr;
4205
Olli Etuahofc1806e2015-03-17 13:03:11 +02004206 switch (op)
4207 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004208 case EOpEqual:
4209 case EOpNotEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04004210 case EOpLessThan:
4211 case EOpGreaterThan:
4212 case EOpLessThanEqual:
4213 case EOpGreaterThanEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04004214 break;
4215 case EOpLogicalOr:
4216 case EOpLogicalXor:
4217 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03004218 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4219 !right->getType().getStruct());
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00004220 if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04004221 {
4222 return nullptr;
4223 }
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00004224 // Basic types matching should have been already checked.
4225 ASSERT(right->getBasicType() == EbtBool);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004226 break;
4227 case EOpAdd:
4228 case EOpSub:
4229 case EOpDiv:
4230 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03004231 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4232 !right->getType().getStruct());
4233 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04004234 {
4235 return nullptr;
4236 }
4237 break;
4238 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03004239 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
4240 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004241 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03004242 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04004243 {
4244 return nullptr;
4245 }
4246 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004247 default:
4248 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02004249 }
4250
Olli Etuaho1dded802016-08-18 18:13:13 +03004251 if (op == EOpMul)
4252 {
4253 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
4254 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4255 {
4256 return nullptr;
4257 }
4258 }
4259
Olli Etuaho3fdec912016-08-18 15:08:06 +03004260 TIntermBinary *node = new TIntermBinary(op, left, right);
4261 node->setLine(loc);
4262
Olli Etuaho3fdec912016-08-18 15:08:06 +03004263 // See if we can fold constants.
Olli Etuaho77ba4082016-12-16 12:01:18 +00004264 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuaho3fdec912016-08-18 15:08:06 +03004265 if (foldedNode)
4266 return foldedNode;
4267
4268 return node;
Olli Etuahofc1806e2015-03-17 13:03:11 +02004269}
4270
Jamie Madillb98c3a82015-07-23 14:26:04 -04004271TIntermTyped *TParseContext::addBinaryMath(TOperator op,
4272 TIntermTyped *left,
4273 TIntermTyped *right,
4274 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004275{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004276 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004277 if (node == 0)
4278 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004279 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4280 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02004281 return left;
4282 }
4283 return node;
4284}
4285
Jamie Madillb98c3a82015-07-23 14:26:04 -04004286TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
4287 TIntermTyped *left,
4288 TIntermTyped *right,
4289 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004290{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004291 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004292 if (node == 0)
4293 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004294 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4295 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04004296 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02004297 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004298 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
4299 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004300 }
4301 return node;
4302}
4303
Olli Etuaho13389b62016-10-16 11:48:18 +01004304TIntermBinary *TParseContext::createAssign(TOperator op,
4305 TIntermTyped *left,
4306 TIntermTyped *right,
4307 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004308{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004309 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004310 {
Olli Etuaho1dded802016-08-18 18:13:13 +03004311 if (op == EOpMulAssign)
4312 {
4313 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
4314 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4315 {
4316 return nullptr;
4317 }
4318 }
Olli Etuaho3fdec912016-08-18 15:08:06 +03004319 TIntermBinary *node = new TIntermBinary(op, left, right);
4320 node->setLine(loc);
4321
Olli Etuaho3fdec912016-08-18 15:08:06 +03004322 return node;
Olli Etuahod6b14282015-03-17 14:31:35 +02004323 }
4324 return nullptr;
4325}
4326
Jamie Madillb98c3a82015-07-23 14:26:04 -04004327TIntermTyped *TParseContext::addAssign(TOperator op,
4328 TIntermTyped *left,
4329 TIntermTyped *right,
4330 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004331{
4332 TIntermTyped *node = createAssign(op, left, right, loc);
4333 if (node == nullptr)
4334 {
4335 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02004336 return left;
4337 }
4338 return node;
4339}
4340
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004341TIntermTyped *TParseContext::addComma(TIntermTyped *left,
4342 TIntermTyped *right,
4343 const TSourceLoc &loc)
4344{
Corentin Wallez0d959252016-07-12 17:26:32 -04004345 // WebGL2 section 5.26, the following results in an error:
4346 // "Sequence operator applied to void, arrays, or structs containing arrays"
Jamie Madilld7b1ab52016-12-12 14:42:19 -05004347 if (mShaderSpec == SH_WEBGL2_SPEC &&
4348 (left->isArray() || left->getBasicType() == EbtVoid ||
4349 left->getType().isStructureContainingArrays() || right->isArray() ||
4350 right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
Corentin Wallez0d959252016-07-12 17:26:32 -04004351 {
4352 error(loc,
4353 "sequence operator is not allowed for void, arrays, or structs containing arrays",
4354 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04004355 }
4356
Olli Etuaho4db7ded2016-10-13 12:23:11 +01004357 return TIntermediate::AddComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004358}
4359
Olli Etuaho49300862015-02-20 14:54:49 +02004360TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
4361{
4362 switch (op)
4363 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004364 case EOpContinue:
4365 if (mLoopNestingLevel <= 0)
4366 {
4367 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004368 }
4369 break;
4370 case EOpBreak:
4371 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
4372 {
4373 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004374 }
4375 break;
4376 case EOpReturn:
4377 if (mCurrentFunctionType->getBasicType() != EbtVoid)
4378 {
4379 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004380 }
4381 break;
4382 default:
4383 // No checks for discard
4384 break;
Olli Etuaho49300862015-02-20 14:54:49 +02004385 }
4386 return intermediate.addBranch(op, loc);
4387}
4388
Jamie Madillb98c3a82015-07-23 14:26:04 -04004389TIntermBranch *TParseContext::addBranch(TOperator op,
4390 TIntermTyped *returnValue,
4391 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02004392{
4393 ASSERT(op == EOpReturn);
4394 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004395 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02004396 {
4397 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004398 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004399 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02004400 {
4401 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004402 }
4403 return intermediate.addBranch(op, returnValue, loc);
4404}
4405
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004406void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
4407{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004408 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Olli Etuahobd674552016-10-06 13:28:42 +01004409 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004410 TIntermNode *offset = nullptr;
4411 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuahoec9232b2017-03-27 17:01:37 +03004412 if (name == "texelFetchOffset" || name == "textureLodOffset" ||
4413 name == "textureProjLodOffset" || name == "textureGradOffset" ||
4414 name == "textureProjGradOffset")
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004415 {
4416 offset = arguments->back();
4417 }
Olli Etuahoec9232b2017-03-27 17:01:37 +03004418 else if (name == "textureOffset" || name == "textureProjOffset")
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004419 {
4420 // A bias parameter might follow the offset parameter.
4421 ASSERT(arguments->size() >= 3);
4422 offset = (*arguments)[2];
4423 }
4424 if (offset != nullptr)
4425 {
4426 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
4427 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
4428 {
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004429 error(functionCall->getLine(), "Texture offset must be a constant expression",
Olli Etuahoec9232b2017-03-27 17:01:37 +03004430 name.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004431 }
4432 else
4433 {
4434 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
4435 size_t size = offsetConstantUnion->getType().getObjectSize();
4436 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
4437 for (size_t i = 0u; i < size; ++i)
4438 {
4439 int offsetValue = values[i].getIConst();
4440 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
4441 {
4442 std::stringstream tokenStream;
4443 tokenStream << offsetValue;
4444 std::string token = tokenStream.str();
4445 error(offset->getLine(), "Texture offset value out of valid range",
4446 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004447 }
4448 }
4449 }
4450 }
4451}
4452
Martin Radev2cc85b32016-08-05 16:22:53 +03004453// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
4454void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
4455{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004456 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Martin Radev2cc85b32016-08-05 16:22:53 +03004457 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
4458
4459 if (name.compare(0, 5, "image") == 0)
4460 {
4461 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuaho485eefd2017-02-14 17:40:06 +00004462 TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
Martin Radev2cc85b32016-08-05 16:22:53 +03004463
Olli Etuaho485eefd2017-02-14 17:40:06 +00004464 const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
Martin Radev2cc85b32016-08-05 16:22:53 +03004465
4466 if (name.compare(5, 5, "Store") == 0)
4467 {
4468 if (memoryQualifier.readonly)
4469 {
4470 error(imageNode->getLine(),
4471 "'imageStore' cannot be used with images qualified as 'readonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004472 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03004473 }
4474 }
4475 else if (name.compare(5, 4, "Load") == 0)
4476 {
4477 if (memoryQualifier.writeonly)
4478 {
4479 error(imageNode->getLine(),
4480 "'imageLoad' cannot be used with images qualified as 'writeonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004481 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03004482 }
4483 }
4484 }
4485}
4486
4487// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
4488void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
4489 const TFunction *functionDefinition,
4490 const TIntermAggregate *functionCall)
4491{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004492 ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
Martin Radev2cc85b32016-08-05 16:22:53 +03004493
4494 const TIntermSequence &arguments = *functionCall->getSequence();
4495
4496 ASSERT(functionDefinition->getParamCount() == arguments.size());
4497
4498 for (size_t i = 0; i < arguments.size(); ++i)
4499 {
Olli Etuaho485eefd2017-02-14 17:40:06 +00004500 TIntermTyped *typedArgument = arguments[i]->getAsTyped();
4501 const TType &functionArgumentType = typedArgument->getType();
Martin Radev2cc85b32016-08-05 16:22:53 +03004502 const TType &functionParameterType = *functionDefinition->getParam(i).type;
4503 ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
4504
4505 if (IsImage(functionArgumentType.getBasicType()))
4506 {
4507 const TMemoryQualifier &functionArgumentMemoryQualifier =
4508 functionArgumentType.getMemoryQualifier();
4509 const TMemoryQualifier &functionParameterMemoryQualifier =
4510 functionParameterType.getMemoryQualifier();
4511 if (functionArgumentMemoryQualifier.readonly &&
4512 !functionParameterMemoryQualifier.readonly)
4513 {
4514 error(functionCall->getLine(),
4515 "Function call discards the 'readonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004516 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03004517 }
4518
4519 if (functionArgumentMemoryQualifier.writeonly &&
4520 !functionParameterMemoryQualifier.writeonly)
4521 {
4522 error(functionCall->getLine(),
4523 "Function call discards the 'writeonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004524 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03004525 }
Martin Radev049edfa2016-11-11 14:35:37 +02004526
4527 if (functionArgumentMemoryQualifier.coherent &&
4528 !functionParameterMemoryQualifier.coherent)
4529 {
4530 error(functionCall->getLine(),
4531 "Function call discards the 'coherent' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004532 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02004533 }
4534
4535 if (functionArgumentMemoryQualifier.volatileQualifier &&
4536 !functionParameterMemoryQualifier.volatileQualifier)
4537 {
4538 error(functionCall->getLine(),
4539 "Function call discards the 'volatile' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00004540 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02004541 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004542 }
4543 }
4544}
4545
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004546TIntermSequence *TParseContext::createEmptyArgumentsList()
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004547{
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004548 return new TIntermSequence();
Olli Etuaho72d10202017-01-19 15:58:30 +00004549}
4550
4551TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004552 TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00004553 TIntermNode *thisNode,
4554 const TSourceLoc &loc)
4555{
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004556 if (thisNode != nullptr)
4557 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004558 return addMethod(fnCall, arguments, thisNode, loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004559 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004560
4561 TOperator op = fnCall->getBuiltInOp();
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004562 if (op == EOpConstruct)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004563 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004564 return addConstructor(arguments, fnCall->getReturnType(), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004565 }
4566 else
4567 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03004568 ASSERT(op == EOpNull);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004569 return addNonConstructorFunctionCall(fnCall, arguments, loc);
4570 }
4571}
4572
4573TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
4574 TIntermSequence *arguments,
4575 TIntermNode *thisNode,
4576 const TSourceLoc &loc)
4577{
4578 TConstantUnion *unionArray = new TConstantUnion[1];
4579 int arraySize = 0;
4580 TIntermTyped *typedThis = thisNode->getAsTyped();
4581 // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
4582 // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
4583 // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
4584 // So accessing fnCall->getName() below is safe.
4585 if (fnCall->getName() != "length")
4586 {
4587 error(loc, "invalid method", fnCall->getName().c_str());
4588 }
4589 else if (!arguments->empty())
4590 {
4591 error(loc, "method takes no parameters", "length");
4592 }
4593 else if (typedThis == nullptr || !typedThis->isArray())
4594 {
4595 error(loc, "length can only be called on arrays", "length");
4596 }
4597 else
4598 {
4599 arraySize = typedThis->getArraySize();
4600 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuaho72d10202017-01-19 15:58:30 +00004601 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004602 // This code path can be hit with expressions like these:
4603 // (a = b).length()
4604 // (func()).length()
4605 // (int[3](0, 1, 2)).length()
4606 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
4607 // expression.
4608 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
4609 // spec section 5.9 which allows "An array, vector or matrix expression with the
4610 // length method applied".
4611 error(loc, "length can only be called on array names, not on array expressions",
4612 "length");
Olli Etuaho72d10202017-01-19 15:58:30 +00004613 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004614 }
4615 unionArray->setIConst(arraySize);
4616 return intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
4617}
4618
4619TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
4620 TIntermSequence *arguments,
4621 const TSourceLoc &loc)
4622{
4623 // First find by unmangled name to check whether the function name has been
4624 // hidden by a variable name or struct typename.
4625 // If a function is found, check for one with a matching argument list.
4626 bool builtIn;
4627 const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn);
4628 if (symbol != nullptr && !symbol->isFunction())
4629 {
4630 error(loc, "function name expected", fnCall->getName().c_str());
4631 }
4632 else
4633 {
4634 symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments),
4635 mShaderVersion, &builtIn);
4636 if (symbol == nullptr)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004637 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004638 error(loc, "no matching overloaded function found", fnCall->getName().c_str());
4639 }
4640 else
4641 {
4642 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004643 //
4644 // A declared function.
4645 //
Olli Etuaho383b7912016-08-05 11:22:59 +03004646 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004647 {
Olli Etuaho856c4972016-08-08 11:38:39 +03004648 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004649 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004650 TOperator op = fnCandidate->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004651 if (builtIn && op != EOpNull)
4652 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004653 // A function call mapped to a built-in operation.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004654 if (fnCandidate->getParamCount() == 1)
4655 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004656 // Treat it like a built-in unary operator.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004657 TIntermNode *unaryParamNode = arguments->front();
4658 TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004659 ASSERT(callNode != nullptr);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004660 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004661 }
4662 else
4663 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004664 TIntermAggregate *callNode =
Olli Etuahofe486322017-03-21 09:30:54 +00004665 TIntermAggregate::Create(fnCandidate->getReturnType(), op, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004666 callNode->setLine(loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004667
4668 // Some built-in functions have out parameters too.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004669 functionCallLValueErrorCheck(fnCandidate, callNode);
Arun Patole274f0702015-05-05 13:33:30 +05304670
Olli Etuaho7c3848e2015-11-04 13:19:17 +02004671 // See if we can constant fold a built-in. Note that this may be possible even
4672 // if it is not const-qualified.
Olli Etuahof119a262016-08-19 15:54:22 +03004673 TIntermTyped *foldedNode =
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004674 intermediate.foldAggregateBuiltIn(callNode, mDiagnostics);
Arun Patole274f0702015-05-05 13:33:30 +05304675 if (foldedNode)
4676 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004677 return foldedNode;
Arun Patole274f0702015-05-05 13:33:30 +05304678 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004679 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004680 }
4681 }
4682 else
4683 {
4684 // This is a real function call
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004685 TIntermAggregate *callNode = nullptr;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004686
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004687 // If builtIn == false, the function is user defined - could be an overloaded
4688 // built-in as well.
4689 // if builtIn == true, it's a builtIn function with no op associated with it.
4690 // This needs to happen after the function info including name is set.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004691 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004692 {
Olli Etuahofe486322017-03-21 09:30:54 +00004693 callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004694 checkTextureOffsetConst(callNode);
4695 checkImageMemoryAccessForBuiltinFunctions(callNode);
Martin Radev2cc85b32016-08-05 16:22:53 +03004696 }
4697 else
4698 {
Olli Etuahofe486322017-03-21 09:30:54 +00004699 callNode = TIntermAggregate::CreateFunctionCall(*fnCandidate, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004700 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004701 }
4702
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004703 functionCallLValueErrorCheck(fnCandidate, callNode);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004704
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004705 callNode->setLine(loc);
4706
4707 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004708 }
4709 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004710 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004711
4712 // Error message was already written. Put on a dummy node for error recovery.
4713 return TIntermTyped::CreateZero(TType(EbtFloat, EbpMedium, EvqConst));
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004714}
4715
Jamie Madillb98c3a82015-07-23 14:26:04 -04004716TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004717 TIntermTyped *trueExpression,
4718 TIntermTyped *falseExpression,
Olli Etuaho52901742015-04-15 13:42:45 +03004719 const TSourceLoc &loc)
4720{
Olli Etuaho856c4972016-08-08 11:38:39 +03004721 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03004722
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004723 if (trueExpression->getType() != falseExpression->getType())
Olli Etuaho52901742015-04-15 13:42:45 +03004724 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004725 binaryOpError(loc, "?:", trueExpression->getCompleteString(),
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004726 falseExpression->getCompleteString());
4727 return falseExpression;
Olli Etuaho52901742015-04-15 13:42:45 +03004728 }
Olli Etuahode318b22016-10-25 16:18:25 +01004729 if (IsOpaqueType(trueExpression->getBasicType()))
4730 {
4731 // ESSL 1.00 section 4.1.7
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004732 // ESSL 3.00.6 section 4.1.7
Olli Etuahode318b22016-10-25 16:18:25 +01004733 // Opaque/sampler types are not allowed in most types of expressions, including ternary.
4734 // Note that structs containing opaque types don't need to be checked as structs are
4735 // forbidden below.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004736 error(loc, "ternary operator is not allowed for opaque types", "?:");
Olli Etuahode318b22016-10-25 16:18:25 +01004737 return falseExpression;
4738 }
4739
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004740 // ESSL 1.00.17 sections 5.2 and 5.7:
Olli Etuahoa2d53032015-04-15 14:14:44 +03004741 // Ternary operator is not among the operators allowed for structures/arrays.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004742 // ESSL 3.00.6 section 5.7:
4743 // Ternary operator support is optional for arrays. No certainty that it works across all
4744 // devices with struct either, so we err on the side of caution here. TODO (oetuaho@nvidia.com):
4745 // Would be nice to make the spec and implementation agree completely here.
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004746 if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
Olli Etuahoa2d53032015-04-15 14:14:44 +03004747 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004748 error(loc, "ternary operator is not allowed for structures or arrays", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004749 return falseExpression;
Olli Etuahoa2d53032015-04-15 14:14:44 +03004750 }
Olli Etuaho94050052017-05-08 14:17:44 +03004751 if (trueExpression->getBasicType() == EbtInterfaceBlock)
4752 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004753 error(loc, "ternary operator is not allowed for interface blocks", "?:");
Olli Etuaho94050052017-05-08 14:17:44 +03004754 return falseExpression;
4755 }
4756
Corentin Wallez0d959252016-07-12 17:26:32 -04004757 // WebGL2 section 5.26, the following results in an error:
4758 // "Ternary operator applied to void, arrays, or structs containing arrays"
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004759 if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
Corentin Wallez0d959252016-07-12 17:26:32 -04004760 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03004761 error(loc, "ternary operator is not allowed for void", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004762 return falseExpression;
Corentin Wallez0d959252016-07-12 17:26:32 -04004763 }
4764
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004765 return TIntermediate::AddTernarySelection(cond, trueExpression, falseExpression, loc);
Olli Etuaho52901742015-04-15 13:42:45 +03004766}
Olli Etuaho49300862015-02-20 14:54:49 +02004767
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004768//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004769// Parse an array of strings using yyparse.
4770//
4771// Returns 0 for success.
4772//
Jamie Madillb98c3a82015-07-23 14:26:04 -04004773int PaParseStrings(size_t count,
4774 const char *const string[],
4775 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05304776 TParseContext *context)
4777{
Yunchao He4f285442017-04-21 12:15:49 +08004778 if ((count == 0) || (string == nullptr))
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004779 return 1;
4780
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004781 if (glslang_initialize(context))
4782 return 1;
4783
alokp@chromium.org408c45e2012-04-05 15:54:43 +00004784 int error = glslang_scan(count, string, length, context);
4785 if (!error)
4786 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004787
alokp@chromium.org73bc2982012-06-19 18:48:05 +00004788 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00004789
alokp@chromium.org6b495712012-06-29 00:06:58 +00004790 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004791}
Jamie Madill45bcc782016-11-07 13:58:48 -05004792
4793} // namespace sh