blob: f422f0443b3a7d4aa7ca99b1104b61b54440b576 [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 Etuaho3ec75682017-07-05 17:02:55 +030015#include "compiler/translator/IntermNode_util.h"
Olli Etuahob0c645e2015-05-12 14:25:36 +030016#include "compiler/translator/ValidateGlobalInitializer.h"
jchen104cdac9e2017-05-08 11:01:20 +080017#include "compiler/translator/ValidateSwitch.h"
18#include "compiler/translator/glslang.h"
Olli Etuaho37ad4742015-04-27 13:18:50 +030019#include "compiler/translator/util.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000020
Jamie Madill45bcc782016-11-07 13:58:48 -050021namespace sh
22{
23
alokp@chromium.org8b851c62012-06-15 16:25:11 +000024///////////////////////////////////////////////////////////////////////
25//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000026// Sub- vector and matrix fields
27//
28////////////////////////////////////////////////////////////////////////
29
Martin Radev2cc85b32016-08-05 16:22:53 +030030namespace
31{
32
33const int kWebGLMaxStructNesting = 4;
34
Olli Etuaho0f684632017-07-13 12:42:15 +030035bool ContainsSampler(const TStructure *structType);
36
Martin Radev2cc85b32016-08-05 16:22:53 +030037bool ContainsSampler(const TType &type)
38{
39 if (IsSampler(type.getBasicType()))
Olli Etuaho0f684632017-07-13 12:42:15 +030040 {
Martin Radev2cc85b32016-08-05 16:22:53 +030041 return true;
Olli Etuaho0f684632017-07-13 12:42:15 +030042 }
jchen10cc2a10e2017-05-03 14:05:12 +080043 if (type.getBasicType() == EbtStruct)
Martin Radev2cc85b32016-08-05 16:22:53 +030044 {
Olli Etuaho0f684632017-07-13 12:42:15 +030045 return ContainsSampler(type.getStruct());
Martin Radev2cc85b32016-08-05 16:22:53 +030046 }
47
48 return false;
49}
50
Olli Etuaho0f684632017-07-13 12:42:15 +030051bool ContainsSampler(const TStructure *structType)
52{
53 for (const auto &field : structType->fields())
54 {
55 if (ContainsSampler(*field->type()))
56 return true;
57 }
58 return false;
59}
60
Olli Etuaho485eefd2017-02-14 17:40:06 +000061// Get a token from an image argument to use as an error message token.
62const char *GetImageArgumentToken(TIntermTyped *imageNode)
63{
64 ASSERT(IsImage(imageNode->getBasicType()));
65 while (imageNode->getAsBinaryNode() &&
66 (imageNode->getAsBinaryNode()->getOp() == EOpIndexIndirect ||
67 imageNode->getAsBinaryNode()->getOp() == EOpIndexDirect))
68 {
69 imageNode = imageNode->getAsBinaryNode()->getLeft();
70 }
71 TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode();
72 if (imageSymbol)
73 {
74 return imageSymbol->getSymbol().c_str();
75 }
76 return "image";
77}
78
Olli Etuahocce89652017-06-19 16:04:09 +030079bool CanSetDefaultPrecisionOnType(const TPublicType &type)
80{
81 if (!SupportsPrecision(type.getBasicType()))
82 {
83 return false;
84 }
85 if (type.getBasicType() == EbtUInt)
86 {
87 // ESSL 3.00.4 section 4.5.4
88 return false;
89 }
90 if (type.isAggregate())
91 {
92 // Not allowed to set for aggregate types
93 return false;
94 }
95 return true;
96}
97
Jiawei Shaod8105a02017-08-08 09:54:36 +080098// Map input primitive types to input array sizes in a geometry shader.
99GLuint GetGeometryShaderInputArraySize(TLayoutPrimitiveType primitiveType)
100{
101 switch (primitiveType)
102 {
103 case EptPoints:
104 return 1u;
105 case EptLines:
106 return 2u;
107 case EptTriangles:
108 return 3u;
109 case EptLinesAdjacency:
110 return 4u;
111 case EptTrianglesAdjacency:
112 return 6u;
113 default:
114 UNREACHABLE();
115 return 0u;
116 }
117}
118
Martin Radev2cc85b32016-08-05 16:22:53 +0300119} // namespace
120
jchen104cdac9e2017-05-08 11:01:20 +0800121// This tracks each binding point's current default offset for inheritance of subsequent
122// variables using the same binding, and keeps offsets unique and non overlapping.
123// See GLSL ES 3.1, section 4.4.6.
124class TParseContext::AtomicCounterBindingState
125{
126 public:
127 AtomicCounterBindingState() : mDefaultOffset(0) {}
128 // Inserts a new span and returns -1 if overlapping, else returns the starting offset of
129 // newly inserted span.
130 int insertSpan(int start, size_t length)
131 {
132 gl::RangeI newSpan(start, start + static_cast<int>(length));
133 for (const auto &span : mSpans)
134 {
135 if (newSpan.intersects(span))
136 {
137 return -1;
138 }
139 }
140 mSpans.push_back(newSpan);
141 mDefaultOffset = newSpan.high();
142 return start;
143 }
144 // Inserts a new span starting from the default offset.
145 int appendSpan(size_t length) { return insertSpan(mDefaultOffset, length); }
146 void setDefaultOffset(int offset) { mDefaultOffset = offset; }
147
148 private:
149 int mDefaultOffset;
150 std::vector<gl::RangeI> mSpans;
151};
152
Jamie Madillacb4b812016-11-07 13:50:29 -0500153TParseContext::TParseContext(TSymbolTable &symt,
154 TExtensionBehavior &ext,
155 sh::GLenum type,
156 ShShaderSpec spec,
157 ShCompileOptions options,
158 bool checksPrecErrors,
Olli Etuaho77ba4082016-12-16 12:01:18 +0000159 TDiagnostics *diagnostics,
Jamie Madillacb4b812016-11-07 13:50:29 -0500160 const ShBuiltInResources &resources)
Olli Etuaho56229f12017-07-10 14:16:33 +0300161 : symbolTable(symt),
Olli Etuahobb7e5a72017-04-24 10:16:44 +0300162 mDeferredNonEmptyDeclarationErrorCheck(false),
Jamie Madillacb4b812016-11-07 13:50:29 -0500163 mShaderType(type),
164 mShaderSpec(spec),
165 mCompileOptions(options),
166 mShaderVersion(100),
167 mTreeRoot(nullptr),
168 mLoopNestingLevel(0),
169 mStructNestingLevel(0),
170 mSwitchNestingLevel(0),
171 mCurrentFunctionType(nullptr),
172 mFunctionReturnsValue(false),
173 mChecksPrecisionErrors(checksPrecErrors),
174 mFragmentPrecisionHighOnESSL1(false),
Jiajia Qinbc585152017-06-23 15:42:17 +0800175 mDefaultUniformMatrixPacking(EmpColumnMajor),
176 mDefaultUniformBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
177 mDefaultBufferMatrixPacking(EmpColumnMajor),
178 mDefaultBufferBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
Olli Etuaho77ba4082016-12-16 12:01:18 +0000179 mDiagnostics(diagnostics),
Jamie Madillacb4b812016-11-07 13:50:29 -0500180 mDirectiveHandler(ext,
Olli Etuaho77ba4082016-12-16 12:01:18 +0000181 *mDiagnostics,
Jamie Madillacb4b812016-11-07 13:50:29 -0500182 mShaderVersion,
183 mShaderType,
184 resources.WEBGL_debug_shader_precision == 1),
Olli Etuaho77ba4082016-12-16 12:01:18 +0000185 mPreprocessor(mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()),
Jamie Madillacb4b812016-11-07 13:50:29 -0500186 mScanner(nullptr),
187 mUsesFragData(false),
188 mUsesFragColor(false),
189 mUsesSecondaryOutputs(false),
190 mMinProgramTexelOffset(resources.MinProgramTexelOffset),
191 mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
Olli Etuaho09b04a22016-12-15 13:30:26 +0000192 mMultiviewAvailable(resources.OVR_multiview == 1),
Jamie Madillacb4b812016-11-07 13:50:29 -0500193 mComputeShaderLocalSizeDeclared(false),
Olli Etuaho09b04a22016-12-15 13:30:26 +0000194 mNumViews(-1),
195 mMaxNumViews(resources.MaxViewsOVR),
Olli Etuaho43364892017-02-13 16:00:12 +0000196 mMaxImageUnits(resources.MaxImageUnits),
197 mMaxCombinedTextureImageUnits(resources.MaxCombinedTextureImageUnits),
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000198 mMaxUniformLocations(resources.MaxUniformLocations),
jchen10af713a22017-04-19 09:10:56 +0800199 mMaxUniformBufferBindings(resources.MaxUniformBufferBindings),
jchen104cdac9e2017-05-08 11:01:20 +0800200 mMaxAtomicCounterBindings(resources.MaxAtomicCounterBindings),
Jiajia Qinbc585152017-06-23 15:42:17 +0800201 mMaxShaderStorageBufferBindings(resources.MaxShaderStorageBufferBindings),
Shaob5cc1192017-07-06 10:47:20 +0800202 mDeclaringFunction(false),
203 mGeometryShaderInputPrimitiveType(EptUndefined),
204 mGeometryShaderOutputPrimitiveType(EptUndefined),
205 mGeometryShaderInvocations(0),
206 mGeometryShaderMaxVertices(-1),
207 mMaxGeometryShaderInvocations(resources.MaxGeometryShaderInvocations),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800208 mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices),
209 mGeometryShaderInputArraySize(0)
Jamie Madillacb4b812016-11-07 13:50:29 -0500210{
211 mComputeShaderLocalSize.fill(-1);
212}
213
jchen104cdac9e2017-05-08 11:01:20 +0800214TParseContext::~TParseContext()
215{
216}
217
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300218bool TParseContext::parseVectorFields(const TSourceLoc &line,
219 const TString &compString,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400220 int vecSize,
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300221 TVector<int> *fieldOffsets)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222{
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300223 ASSERT(fieldOffsets);
224 size_t fieldCount = compString.size();
225 if (fieldCount > 4u)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530226 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000227 error(line, "illegal vector field selection", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000228 return false;
229 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300230 fieldOffsets->resize(fieldCount);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000231
Jamie Madillb98c3a82015-07-23 14:26:04 -0400232 enum
233 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000234 exyzw,
235 ergba,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000236 estpq
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000237 } fieldSet[4];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000238
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300239 for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530240 {
241 switch (compString[i])
242 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400243 case 'x':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300244 (*fieldOffsets)[i] = 0;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400245 fieldSet[i] = exyzw;
246 break;
247 case 'r':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300248 (*fieldOffsets)[i] = 0;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400249 fieldSet[i] = ergba;
250 break;
251 case 's':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300252 (*fieldOffsets)[i] = 0;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400253 fieldSet[i] = estpq;
254 break;
255 case 'y':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300256 (*fieldOffsets)[i] = 1;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400257 fieldSet[i] = exyzw;
258 break;
259 case 'g':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300260 (*fieldOffsets)[i] = 1;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400261 fieldSet[i] = ergba;
262 break;
263 case 't':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300264 (*fieldOffsets)[i] = 1;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400265 fieldSet[i] = estpq;
266 break;
267 case 'z':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300268 (*fieldOffsets)[i] = 2;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400269 fieldSet[i] = exyzw;
270 break;
271 case 'b':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300272 (*fieldOffsets)[i] = 2;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400273 fieldSet[i] = ergba;
274 break;
275 case 'p':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300276 (*fieldOffsets)[i] = 2;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400277 fieldSet[i] = estpq;
278 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530279
Jamie Madillb98c3a82015-07-23 14:26:04 -0400280 case 'w':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300281 (*fieldOffsets)[i] = 3;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400282 fieldSet[i] = exyzw;
283 break;
284 case 'a':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300285 (*fieldOffsets)[i] = 3;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400286 fieldSet[i] = ergba;
287 break;
288 case 'q':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300289 (*fieldOffsets)[i] = 3;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400290 fieldSet[i] = estpq;
291 break;
292 default:
293 error(line, "illegal vector field selection", compString.c_str());
294 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000295 }
296 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000297
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300298 for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530299 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300300 if ((*fieldOffsets)[i] >= vecSize)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530301 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400302 error(line, "vector field selection out of range", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000303 return false;
304 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000305
Arun Patole7e7e68d2015-05-22 12:02:25 +0530306 if (i > 0)
307 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400308 if (fieldSet[i] != fieldSet[i - 1])
Arun Patole7e7e68d2015-05-22 12:02:25 +0530309 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400310 error(line, "illegal - vector component fields not from the same set",
311 compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000312 return false;
313 }
314 }
315 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000316
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000317 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000318}
319
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000320///////////////////////////////////////////////////////////////////////
321//
322// Errors
323//
324////////////////////////////////////////////////////////////////////////
325
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000326//
327// Used by flex/bison to output all syntax and parsing errors.
328//
Olli Etuaho4de340a2016-12-16 09:32:03 +0000329void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000330{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000331 mDiagnostics->error(loc, reason, token);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000332}
333
Olli Etuaho4de340a2016-12-16 09:32:03 +0000334void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530335{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000336 mDiagnostics->warning(loc, reason, token);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +0000337}
338
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200339void TParseContext::outOfRangeError(bool isError,
340 const TSourceLoc &loc,
341 const char *reason,
Olli Etuaho4de340a2016-12-16 09:32:03 +0000342 const char *token)
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200343{
344 if (isError)
345 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000346 error(loc, reason, token);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200347 }
348 else
349 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000350 warning(loc, reason, token);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200351 }
352}
353
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000354//
355// Same error message for all places assignments don't work.
356//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530357void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000358{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000359 std::stringstream reasonStream;
360 reasonStream << "cannot convert from '" << right << "' to '" << left << "'";
361 std::string reason = reasonStream.str();
362 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363}
364
365//
366// Same error message for all places unary operations don't work.
367//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530368void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000369{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000370 std::stringstream reasonStream;
371 reasonStream << "wrong operand type - no operation '" << op
372 << "' exists that takes an operand of type " << operand
373 << " (or there is no acceptable conversion)";
374 std::string reason = reasonStream.str();
375 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000376}
377
378//
379// Same error message for all binary operations don't work.
380//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400381void TParseContext::binaryOpError(const TSourceLoc &line,
382 const char *op,
383 TString left,
384 TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000385{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000386 std::stringstream reasonStream;
387 reasonStream << "wrong operand types - no operation '" << op
388 << "' exists that takes a left-hand operand of type '" << left
389 << "' and a right operand of type '" << right
390 << "' (or there is no acceptable conversion)";
391 std::string reason = reasonStream.str();
392 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393}
394
Olli Etuaho856c4972016-08-08 11:38:39 +0300395void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
396 TPrecision precision,
397 TBasicType type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530398{
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400399 if (!mChecksPrecisionErrors)
Olli Etuaho383b7912016-08-05 11:22:59 +0300400 return;
Martin Radev70866b82016-07-22 15:27:42 +0300401
402 if (precision != EbpUndefined && !SupportsPrecision(type))
403 {
404 error(line, "illegal type for precision qualifier", getBasicString(type));
405 }
406
Olli Etuaho183d7e22015-11-20 15:59:09 +0200407 if (precision == EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530408 {
Olli Etuaho183d7e22015-11-20 15:59:09 +0200409 switch (type)
410 {
411 case EbtFloat:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400412 error(line, "No precision specified for (float)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300413 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200414 case EbtInt:
415 case EbtUInt:
416 UNREACHABLE(); // there's always a predeclared qualifier
Jamie Madillb98c3a82015-07-23 14:26:04 -0400417 error(line, "No precision specified (int)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300418 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200419 default:
jchen10cc2a10e2017-05-03 14:05:12 +0800420 if (IsOpaqueType(type))
Olli Etuaho183d7e22015-11-20 15:59:09 +0200421 {
jchen10cc2a10e2017-05-03 14:05:12 +0800422 error(line, "No precision specified", getBasicString(type));
Martin Radev2cc85b32016-08-05 16:22:53 +0300423 return;
424 }
Olli Etuaho183d7e22015-11-20 15:59:09 +0200425 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000426 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000427}
428
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429// Both test and if necessary, spit out an error, to see if the node is really
430// an l-value that can be operated on this way.
Olli Etuaho856c4972016-08-08 11:38:39 +0300431bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000432{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500433 TIntermSymbol *symNode = node->getAsSymbolNode();
434 TIntermBinary *binaryNode = node->getAsBinaryNode();
Olli Etuahob6fa0432016-09-28 16:28:05 +0100435 TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
436
437 if (swizzleNode)
438 {
439 bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
440 if (ok && swizzleNode->hasDuplicateOffsets())
441 {
442 error(line, " l-value of swizzle cannot have duplicate components", op);
443 return false;
444 }
445 return ok;
446 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000447
Arun Patole7e7e68d2015-05-22 12:02:25 +0530448 if (binaryNode)
449 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400450 switch (binaryNode->getOp())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530451 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400452 case EOpIndexDirect:
453 case EOpIndexIndirect:
454 case EOpIndexDirectStruct:
455 case EOpIndexDirectInterfaceBlock:
Olli Etuaho856c4972016-08-08 11:38:39 +0300456 return checkCanBeLValue(line, op, binaryNode->getLeft());
Jamie Madillb98c3a82015-07-23 14:26:04 -0400457 default:
458 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000459 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000460 error(line, " l-value required", op);
Olli Etuaho8a176262016-08-16 14:23:01 +0300461 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000462 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000463
jchen10cc2a10e2017-05-03 14:05:12 +0800464 std::string message;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530465 switch (node->getQualifier())
466 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400467 case EvqConst:
468 message = "can't modify a const";
469 break;
470 case EvqConstReadOnly:
471 message = "can't modify a const";
472 break;
473 case EvqAttribute:
474 message = "can't modify an attribute";
475 break;
476 case EvqFragmentIn:
477 message = "can't modify an input";
478 break;
479 case EvqVertexIn:
480 message = "can't modify an input";
481 break;
482 case EvqUniform:
483 message = "can't modify a uniform";
484 break;
485 case EvqVaryingIn:
486 message = "can't modify a varying";
487 break;
488 case EvqFragCoord:
489 message = "can't modify gl_FragCoord";
490 break;
491 case EvqFrontFacing:
492 message = "can't modify gl_FrontFacing";
493 break;
494 case EvqPointCoord:
495 message = "can't modify gl_PointCoord";
496 break;
Martin Radevb0883602016-08-04 17:48:58 +0300497 case EvqNumWorkGroups:
498 message = "can't modify gl_NumWorkGroups";
499 break;
500 case EvqWorkGroupSize:
501 message = "can't modify gl_WorkGroupSize";
502 break;
503 case EvqWorkGroupID:
504 message = "can't modify gl_WorkGroupID";
505 break;
506 case EvqLocalInvocationID:
507 message = "can't modify gl_LocalInvocationID";
508 break;
509 case EvqGlobalInvocationID:
510 message = "can't modify gl_GlobalInvocationID";
511 break;
512 case EvqLocalInvocationIndex:
513 message = "can't modify gl_LocalInvocationIndex";
514 break;
Olli Etuaho7142f6c2017-05-05 17:07:26 +0300515 case EvqViewIDOVR:
516 message = "can't modify gl_ViewID_OVR";
517 break;
Martin Radev802abe02016-08-04 17:48:32 +0300518 case EvqComputeIn:
519 message = "can't modify work group size variable";
520 break;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800521 case EvqPerVertexIn:
522 message = "can't modify any member in gl_in";
523 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400524 default:
525 //
526 // Type that can't be written to?
527 //
528 if (node->getBasicType() == EbtVoid)
529 {
530 message = "can't modify void";
531 }
jchen10cc2a10e2017-05-03 14:05:12 +0800532 if (IsOpaqueType(node->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -0400533 {
jchen10cc2a10e2017-05-03 14:05:12 +0800534 message = "can't modify a variable with type ";
535 message += getBasicString(node->getBasicType());
Martin Radev2cc85b32016-08-05 16:22:53 +0300536 }
Jiajia Qinbc585152017-06-23 15:42:17 +0800537 else if (node->getMemoryQualifier().readonly)
538 {
539 message = "can't modify a readonly variable";
540 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000541 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000542
jchen10cc2a10e2017-05-03 14:05:12 +0800543 if (message.empty() && binaryNode == 0 && symNode == 0)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530544 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000545 error(line, "l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000546
Olli Etuaho8a176262016-08-16 14:23:01 +0300547 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000548 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000549
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000550 //
551 // Everything else is okay, no error.
552 //
jchen10cc2a10e2017-05-03 14:05:12 +0800553 if (message.empty())
Olli Etuaho8a176262016-08-16 14:23:01 +0300554 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000555
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000556 //
557 // If we get here, we have an error and a message.
558 //
Arun Patole7e7e68d2015-05-22 12:02:25 +0530559 if (symNode)
560 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000561 const char *symbol = symNode->getSymbol().c_str();
562 std::stringstream reasonStream;
563 reasonStream << "l-value required (" << message << " \"" << symbol << "\")";
564 std::string reason = reasonStream.str();
565 error(line, reason.c_str(), op);
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000566 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530567 else
568 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000569 std::stringstream reasonStream;
570 reasonStream << "l-value required (" << message << ")";
571 std::string reason = reasonStream.str();
572 error(line, reason.c_str(), op);
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000573 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000574
Olli Etuaho8a176262016-08-16 14:23:01 +0300575 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000576}
577
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000578// Both test, and if necessary spit out an error, to see if the node is really
579// a constant.
Olli Etuaho856c4972016-08-08 11:38:39 +0300580void TParseContext::checkIsConst(TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000581{
Olli Etuaho383b7912016-08-05 11:22:59 +0300582 if (node->getQualifier() != EvqConst)
583 {
584 error(node->getLine(), "constant expression required", "");
585 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000586}
587
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000588// Both test, and if necessary spit out an error, to see if the node is really
589// an integer.
Olli Etuaho856c4972016-08-08 11:38:39 +0300590void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000591{
Olli Etuaho383b7912016-08-05 11:22:59 +0300592 if (!node->isScalarInt())
593 {
594 error(node->getLine(), "integer expression required", token);
595 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000596}
597
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000598// Both test, and if necessary spit out an error, to see if we are currently
599// globally scoped.
Qiankun Miaof69682b2016-08-16 14:50:42 +0800600bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000601{
Olli Etuaho856c4972016-08-08 11:38:39 +0300602 if (!symbolTable.atGlobalLevel())
Olli Etuaho383b7912016-08-05 11:22:59 +0300603 {
604 error(line, "only allowed at global scope", token);
Qiankun Miaof69682b2016-08-16 14:50:42 +0800605 return false;
Olli Etuaho383b7912016-08-05 11:22:59 +0300606 }
Qiankun Miaof69682b2016-08-16 14:50:42 +0800607 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000608}
609
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300610// ESSL 3.00.5 sections 3.8 and 3.9.
611// If it starts "gl_" or contains two consecutive underscores, it's reserved.
612// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a webgl shader.
Olli Etuaho856c4972016-08-08 11:38:39 +0300613bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000614{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530615 static const char *reservedErrMsg = "reserved built-in name";
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300616 if (identifier.compare(0, 3, "gl_") == 0)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530617 {
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300618 error(line, reservedErrMsg, "gl_");
619 return false;
620 }
621 if (sh::IsWebGLBasedSpec(mShaderSpec))
622 {
623 if (identifier.compare(0, 6, "webgl_") == 0)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530624 {
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300625 error(line, reservedErrMsg, "webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300626 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000627 }
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300628 if (identifier.compare(0, 7, "_webgl_") == 0)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530629 {
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300630 error(line, reservedErrMsg, "_webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300631 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000632 }
633 }
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300634 if (identifier.find("__") != TString::npos)
635 {
636 error(line,
637 "identifiers containing two consecutive underscores (__) are reserved as "
638 "possible future keywords",
639 identifier.c_str());
640 return false;
641 }
Olli Etuaho8a176262016-08-16 14:23:01 +0300642 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000643}
644
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300645// Make sure the argument types are correct for constructing a specific type.
Olli Etuaho856c4972016-08-08 11:38:39 +0300646bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800647 const TIntermSequence *arguments,
Olli Etuaho856c4972016-08-08 11:38:39 +0300648 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000649{
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800650 if (arguments->empty())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530651 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200652 error(line, "constructor does not have any arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300653 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000654 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200655
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300656 for (TIntermNode *arg : *arguments)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530657 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300658 const TIntermTyped *argTyped = arg->getAsTyped();
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200659 ASSERT(argTyped != nullptr);
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300660 if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType()))
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200661 {
jchen10cc2a10e2017-05-03 14:05:12 +0800662 std::string reason("cannot convert a variable with type ");
663 reason += getBasicString(argTyped->getBasicType());
664 error(line, reason.c_str(), "constructor");
Martin Radev2cc85b32016-08-05 16:22:53 +0300665 return false;
666 }
Jiajia Qinbc585152017-06-23 15:42:17 +0800667 else if (argTyped->getMemoryQualifier().writeonly)
668 {
669 error(line, "cannot convert a variable with writeonly", "constructor");
670 return false;
671 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200672 if (argTyped->getBasicType() == EbtVoid)
673 {
674 error(line, "cannot convert a void", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300675 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200676 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000677 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000678
Olli Etuaho856c4972016-08-08 11:38:39 +0300679 if (type.isArray())
680 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300681 // The size of an unsized constructor should already have been determined.
682 ASSERT(!type.isUnsizedArray());
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300683 if (static_cast<size_t>(type.getOutermostArraySize()) != arguments->size())
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300684 {
685 error(line, "array constructor needs one argument per array element", "constructor");
686 return false;
687 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300688 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
689 // the array.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800690 for (TIntermNode *const &argNode : *arguments)
Olli Etuaho856c4972016-08-08 11:38:39 +0300691 {
692 const TType &argType = argNode->getAsTyped()->getType();
Jamie Madill34bf2d92017-02-06 13:40:59 -0500693 if (argType.isArray())
694 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300695 error(line, "constructing from a non-dereferenced array", "constructor");
Jamie Madill34bf2d92017-02-06 13:40:59 -0500696 return false;
697 }
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300698 if (!argType.isElementTypeOf(type))
Olli Etuaho856c4972016-08-08 11:38:39 +0300699 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000700 error(line, "Array constructor argument has an incorrect type", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300701 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300702 }
703 }
704 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300705 else if (type.getBasicType() == EbtStruct)
Olli Etuaho856c4972016-08-08 11:38:39 +0300706 {
707 const TFieldList &fields = type.getStruct()->fields();
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300708 if (fields.size() != arguments->size())
709 {
710 error(line,
711 "Number of constructor parameters does not match the number of structure fields",
712 "constructor");
713 return false;
714 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300715
716 for (size_t i = 0; i < fields.size(); i++)
717 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800718 if (i >= arguments->size() ||
719 (*arguments)[i]->getAsTyped()->getType() != *fields[i]->type())
Olli Etuaho856c4972016-08-08 11:38:39 +0300720 {
721 error(line, "Structure constructor arguments do not match structure fields",
Olli Etuaho4de340a2016-12-16 09:32:03 +0000722 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300723 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300724 }
725 }
726 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300727 else
728 {
729 // We're constructing a scalar, vector, or matrix.
730
731 // Note: It's okay to have too many components available, but not okay to have unused
732 // arguments. 'full' will go to true when enough args have been seen. If we loop again,
733 // there is an extra argument, so 'overFull' will become true.
734
735 size_t size = 0;
736 bool full = false;
737 bool overFull = false;
738 bool matrixArg = false;
739 for (TIntermNode *arg : *arguments)
740 {
741 const TIntermTyped *argTyped = arg->getAsTyped();
742 ASSERT(argTyped != nullptr);
743
Olli Etuaho487b63a2017-05-23 15:55:09 +0300744 if (argTyped->getBasicType() == EbtStruct)
745 {
746 error(line, "a struct cannot be used as a constructor argument for this type",
747 "constructor");
748 return false;
749 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300750 if (argTyped->getType().isArray())
751 {
752 error(line, "constructing from a non-dereferenced array", "constructor");
753 return false;
754 }
755 if (argTyped->getType().isMatrix())
756 {
757 matrixArg = true;
758 }
759
760 size += argTyped->getType().getObjectSize();
761 if (full)
762 {
763 overFull = true;
764 }
Olli Etuaho487b63a2017-05-23 15:55:09 +0300765 if (size >= type.getObjectSize())
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300766 {
767 full = true;
768 }
769 }
770
771 if (type.isMatrix() && matrixArg)
772 {
773 if (arguments->size() != 1)
774 {
775 error(line, "constructing matrix from matrix can only take one argument",
776 "constructor");
777 return false;
778 }
779 }
780 else
781 {
782 if (size != 1 && size < type.getObjectSize())
783 {
784 error(line, "not enough data provided for construction", "constructor");
785 return false;
786 }
787 if (overFull)
788 {
789 error(line, "too many arguments", "constructor");
790 return false;
791 }
792 }
793 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300794
Olli Etuaho8a176262016-08-16 14:23:01 +0300795 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000796}
797
Jamie Madillb98c3a82015-07-23 14:26:04 -0400798// This function checks to see if a void variable has been declared and raise an error message for
799// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000800//
801// returns true in case of an error
802//
Olli Etuaho856c4972016-08-08 11:38:39 +0300803bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400804 const TString &identifier,
805 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000806{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300807 if (type == EbtVoid)
808 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000809 error(line, "illegal use of type 'void'", identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300810 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300811 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000812
Olli Etuaho8a176262016-08-16 14:23:01 +0300813 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000814}
815
Jamie Madillb98c3a82015-07-23 14:26:04 -0400816// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300817// or not.
Olli Etuaho56229f12017-07-10 14:16:33 +0300818bool TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000819{
Olli Etuaho37d96cc2017-07-11 14:14:03 +0300820 if (type->getBasicType() != EbtBool || !type->isScalar())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530821 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000822 error(line, "boolean expression expected", "");
Olli Etuaho56229f12017-07-10 14:16:33 +0300823 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530824 }
Olli Etuaho56229f12017-07-10 14:16:33 +0300825 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000826}
827
Jamie Madillb98c3a82015-07-23 14:26:04 -0400828// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300829// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300830void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000831{
Martin Radev4a9cd802016-09-01 16:51:51 +0300832 if (pType.getBasicType() != EbtBool || pType.isAggregate())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530833 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000834 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530835 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000836}
837
jchen10cc2a10e2017-05-03 14:05:12 +0800838bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
839 const TTypeSpecifierNonArray &pType,
840 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000841{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530842 if (pType.type == EbtStruct)
843 {
Olli Etuaho0f684632017-07-13 12:42:15 +0300844 if (ContainsSampler(pType.userDef))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530845 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000846 std::stringstream reasonStream;
847 reasonStream << reason << " (structure contains a sampler)";
848 std::string reasonStr = reasonStream.str();
849 error(line, reasonStr.c_str(), getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300850 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000851 }
jchen10cc2a10e2017-05-03 14:05:12 +0800852 // only samplers need to be checked from structs, since other opaque types can't be struct
853 // members.
Olli Etuaho8a176262016-08-16 14:23:01 +0300854 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530855 }
jchen10cc2a10e2017-05-03 14:05:12 +0800856 else if (IsOpaqueType(pType.type))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530857 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000858 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300859 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000860 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000861
Olli Etuaho8a176262016-08-16 14:23:01 +0300862 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000863}
864
Olli Etuaho856c4972016-08-08 11:38:39 +0300865void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
866 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400867{
868 if (pType.layoutQualifier.location != -1)
869 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400870 error(line, "location must only be specified for a single input or output variable",
871 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400872 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400873}
874
Olli Etuaho856c4972016-08-08 11:38:39 +0300875void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
876 const TLayoutQualifier &layoutQualifier)
877{
878 if (layoutQualifier.location != -1)
879 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000880 const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs";
881 if (mShaderVersion >= 310)
882 {
883 errorMsg =
884 "invalid layout qualifier: only valid on program inputs, outputs, and uniforms";
885 }
886 error(location, errorMsg, "location");
Olli Etuaho856c4972016-08-08 11:38:39 +0300887 }
888}
889
Martin Radev2cc85b32016-08-05 16:22:53 +0300890void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
891 TQualifier qualifier,
892 const TType &type)
893{
Martin Radev2cc85b32016-08-05 16:22:53 +0300894 ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
jchen10cc2a10e2017-05-03 14:05:12 +0800895 if (IsOpaqueType(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530896 {
jchen10cc2a10e2017-05-03 14:05:12 +0800897 error(line, "opaque types cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000898 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000899}
900
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000901// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300902unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000903{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530904 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000905
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200906 // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
907 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
908 // fold as array size.
909 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000910 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000911 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300912 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000913 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000914
Olli Etuaho856c4972016-08-08 11:38:39 +0300915 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400916
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000917 if (constant->getBasicType() == EbtUInt)
918 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300919 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000920 }
921 else
922 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300923 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000924
Olli Etuaho856c4972016-08-08 11:38:39 +0300925 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000926 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400927 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300928 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000929 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400930
Olli Etuaho856c4972016-08-08 11:38:39 +0300931 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -0400932 }
933
Olli Etuaho856c4972016-08-08 11:38:39 +0300934 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -0400935 {
936 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300937 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400938 }
939
940 // The size of arrays is restricted here to prevent issues further down the
941 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
942 // 4096 registers so this should be reasonable even for aggressively optimizable code.
943 const unsigned int sizeLimit = 65536;
944
Olli Etuaho856c4972016-08-08 11:38:39 +0300945 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -0400946 {
947 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300948 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000949 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300950
951 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000952}
953
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000954// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +0300955bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
956 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000957{
Olli Etuaho8a176262016-08-16 14:23:01 +0300958 if ((elementQualifier.qualifier == EvqAttribute) ||
959 (elementQualifier.qualifier == EvqVertexIn) ||
960 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +0300961 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400962 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300963 TType(elementQualifier).getQualifierString());
964 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000965 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000966
Olli Etuaho8a176262016-08-16 14:23:01 +0300967 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000968}
969
Olli Etuaho8a176262016-08-16 14:23:01 +0300970// See if this element type can be formed into an array.
971bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000972{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000973 //
974 // Can the type be an array?
975 //
Olli Etuaho8a176262016-08-16 14:23:01 +0300976 if (elementType.array)
Jamie Madill06145232015-05-13 13:10:01 -0400977 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300978 error(line, "cannot declare arrays of arrays",
979 TType(elementType).getCompleteString().c_str());
980 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000981 }
Olli Etuahocc36b982015-07-10 14:14:18 +0300982 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
983 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
984 // 4.3.4).
Martin Radev4a9cd802016-09-01 16:51:51 +0300985 if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
Olli Etuaho8a176262016-08-16 14:23:01 +0300986 sh::IsVarying(elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +0300987 {
988 error(line, "cannot declare arrays of structs of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300989 TType(elementType).getCompleteString().c_str());
990 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +0300991 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000992
Olli Etuaho8a176262016-08-16 14:23:01 +0300993 return true;
994}
995
996// Check if this qualified element type can be formed into an array.
997bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
998 const TPublicType &elementType)
999{
1000 if (checkIsValidTypeForArray(indexLocation, elementType))
1001 {
1002 return checkIsValidQualifierForArray(indexLocation, elementType);
1003 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001004 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001005}
1006
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001007// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +03001008void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
1009 const TString &identifier,
1010 TPublicType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001011{
Olli Etuaho3739d232015-04-08 12:23:44 +03001012 ASSERT(type != nullptr);
1013 if (type->qualifier == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +00001014 {
1015 // Make the qualifier make sense.
Olli Etuaho3739d232015-04-08 12:23:44 +03001016 type->qualifier = EvqTemporary;
1017
1018 // Generate informative error messages for ESSL1.
1019 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001020 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +00001021 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05301022 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001023 "structures containing arrays may not be declared constant since they cannot be "
1024 "initialized",
Arun Patole7e7e68d2015-05-22 12:02:25 +05301025 identifier.c_str());
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +00001026 }
1027 else
1028 {
1029 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
1030 }
Olli Etuaho383b7912016-08-05 11:22:59 +03001031 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001032 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03001033 if (type->isUnsizedArray())
1034 {
1035 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
Olli Etuaho376f1b52015-04-13 13:23:41 +03001036 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001037}
1038
Olli Etuaho2935c582015-04-08 14:32:06 +03001039// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001040// and update the symbol table.
1041//
Olli Etuaho2935c582015-04-08 14:32:06 +03001042// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001043//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001044bool TParseContext::declareVariable(const TSourceLoc &line,
1045 const TString &identifier,
1046 const TType &type,
Olli Etuaho2935c582015-04-08 14:32:06 +03001047 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001048{
Olli Etuaho2935c582015-04-08 14:32:06 +03001049 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001050
Olli Etuaho43364892017-02-13 16:00:12 +00001051 checkBindingIsValid(line, type);
1052
Olli Etuaho856c4972016-08-08 11:38:39 +03001053 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001054
Olli Etuaho2935c582015-04-08 14:32:06 +03001055 // gl_LastFragData may be redeclared with a new precision qualifier
1056 if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
1057 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001058 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
1059 symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001060 if (type.isArrayOfArrays())
1061 {
1062 error(line, "redeclaration of gl_LastFragData as an array of arrays",
1063 identifier.c_str());
1064 return false;
1065 }
1066 else if (static_cast<int>(type.getOutermostArraySize()) ==
1067 maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +03001068 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001069 if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +03001070 {
Olli Etuaho8a176262016-08-16 14:23:01 +03001071 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
Olli Etuaho2935c582015-04-08 14:32:06 +03001072 }
1073 }
1074 else
1075 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001076 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
1077 identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +03001078 return false;
1079 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001080 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001081
Olli Etuaho8a176262016-08-16 14:23:01 +03001082 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +03001083 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001084
Olli Etuaho0f684632017-07-13 12:42:15 +03001085 (*variable) = symbolTable.declareVariable(&identifier, type);
1086 if (!(*variable))
Olli Etuaho2935c582015-04-08 14:32:06 +03001087 {
1088 error(line, "redefinition", identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +03001089 return false;
1090 }
1091
Olli Etuaho8a176262016-08-16 14:23:01 +03001092 if (!checkIsNonVoid(line, identifier, type.getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +03001093 return false;
1094
1095 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001096}
1097
Martin Radev70866b82016-07-22 15:27:42 +03001098void TParseContext::checkIsParameterQualifierValid(
1099 const TSourceLoc &line,
1100 const TTypeQualifierBuilder &typeQualifierBuilder,
1101 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301102{
Olli Etuahocce89652017-06-19 16:04:09 +03001103 // The only parameter qualifiers a parameter can have are in, out, inout or const.
Olli Etuaho77ba4082016-12-16 12:01:18 +00001104 TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03001105
1106 if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301107 {
Martin Radev2cc85b32016-08-05 16:22:53 +03001108 checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type);
1109 }
1110
1111 if (!IsImage(type->getBasicType()))
1112 {
Olli Etuaho43364892017-02-13 16:00:12 +00001113 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line);
Martin Radev2cc85b32016-08-05 16:22:53 +03001114 }
1115 else
1116 {
1117 type->setMemoryQualifier(typeQualifier.memoryQualifier);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001118 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001119
Martin Radev70866b82016-07-22 15:27:42 +03001120 type->setQualifier(typeQualifier.qualifier);
1121
1122 if (typeQualifier.precision != EbpUndefined)
1123 {
1124 type->setPrecision(typeQualifier.precision);
1125 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001126}
1127
Olli Etuaho856c4972016-08-08 11:38:39 +03001128bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001129{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001130 const TExtensionBehavior &extBehavior = extensionBehavior();
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001131 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
Arun Patole7e7e68d2015-05-22 12:02:25 +05301132 if (iter == extBehavior.end())
1133 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001134 error(line, "extension is not supported", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001135 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001136 }
zmo@google.comf5450912011-09-09 01:37:19 +00001137 // In GLSL ES, an extension's default behavior is "disable".
Arun Patole7e7e68d2015-05-22 12:02:25 +05301138 if (iter->second == EBhDisable || iter->second == EBhUndefined)
1139 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00001140 // TODO(oetuaho@nvidia.com): This is slightly hacky. Might be better if symbols could be
1141 // associated with more than one extension.
1142 if (extension == "GL_OVR_multiview")
1143 {
1144 return checkCanUseExtension(line, "GL_OVR_multiview2");
1145 }
Olli Etuaho4de340a2016-12-16 09:32:03 +00001146 error(line, "extension is disabled", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001147 return false;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001148 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301149 if (iter->second == EBhWarn)
1150 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001151 warning(line, "extension is being used", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001152 return true;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001153 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001154
Olli Etuaho8a176262016-08-16 14:23:01 +03001155 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001156}
1157
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001158// ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause
1159// compile-time or link-time errors are the same whether or not the declaration is empty".
1160// This function implements all the checks that are done on qualifiers regardless of if the
1161// declaration is empty.
1162void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier,
1163 const sh::TLayoutQualifier &layoutQualifier,
1164 const TSourceLoc &location)
1165{
1166 if (qualifier == EvqShared && !layoutQualifier.isEmpty())
1167 {
1168 error(location, "Shared memory declarations cannot have layout specified", "layout");
1169 }
1170
1171 if (layoutQualifier.matrixPacking != EmpUnspecified)
1172 {
1173 error(location, "layout qualifier only valid for interface blocks",
1174 getMatrixPackingString(layoutQualifier.matrixPacking));
1175 return;
1176 }
1177
1178 if (layoutQualifier.blockStorage != EbsUnspecified)
1179 {
1180 error(location, "layout qualifier only valid for interface blocks",
1181 getBlockStorageString(layoutQualifier.blockStorage));
1182 return;
1183 }
1184
1185 if (qualifier == EvqFragmentOut)
1186 {
1187 if (layoutQualifier.location != -1 && layoutQualifier.yuv == true)
1188 {
1189 error(location, "invalid layout qualifier combination", "yuv");
1190 return;
1191 }
1192 }
1193 else
1194 {
1195 checkYuvIsNotSpecified(location, layoutQualifier.yuv);
1196 }
1197
Olli Etuaho95468d12017-05-04 11:14:34 +03001198 // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous
1199 // parsing steps. So it needs to be checked here.
1200 if (isMultiviewExtensionEnabled() && mShaderVersion < 300 && qualifier == EvqVertexIn)
1201 {
1202 error(location, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
1203 }
1204
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001205 bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut;
1206 if (mShaderVersion >= 310 && qualifier == EvqUniform)
1207 {
1208 canHaveLocation = true;
1209 // We're not checking whether the uniform location is in range here since that depends on
1210 // the type of the variable.
1211 // The type can only be fully determined for non-empty declarations.
1212 }
1213 if (!canHaveLocation)
1214 {
1215 checkLocationIsNotSpecified(location, layoutQualifier);
1216 }
1217}
1218
jchen104cdac9e2017-05-08 11:01:20 +08001219void TParseContext::atomicCounterQualifierErrorCheck(const TPublicType &publicType,
1220 const TSourceLoc &location)
1221{
1222 if (publicType.precision != EbpHigh)
1223 {
1224 error(location, "Can only be highp", "atomic counter");
1225 }
1226 // dEQP enforces compile error if location is specified. See uniform_location.test.
1227 if (publicType.layoutQualifier.location != -1)
1228 {
1229 error(location, "location must not be set for atomic_uint", "layout");
1230 }
1231 if (publicType.layoutQualifier.binding == -1)
1232 {
1233 error(location, "no binding specified", "atomic counter");
1234 }
1235}
1236
Martin Radevb8b01222016-11-20 23:25:53 +02001237void TParseContext::emptyDeclarationErrorCheck(const TPublicType &publicType,
1238 const TSourceLoc &location)
1239{
1240 if (publicType.isUnsizedArray())
1241 {
1242 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1243 // error. It is assumed that this applies to empty declarations as well.
1244 error(location, "empty array declaration needs to specify a size", "");
1245 }
Martin Radevb8b01222016-11-20 23:25:53 +02001246}
1247
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001248// These checks are done for all declarations that are non-empty. They're done for non-empty
1249// declarations starting a declarator list, and declarators that follow an empty declaration.
1250void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
1251 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -04001252{
Olli Etuahofa33d582015-04-09 14:33:12 +03001253 switch (publicType.qualifier)
1254 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001255 case EvqVaryingIn:
1256 case EvqVaryingOut:
1257 case EvqAttribute:
1258 case EvqVertexIn:
1259 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +03001260 case EvqComputeIn:
Martin Radev4a9cd802016-09-01 16:51:51 +03001261 if (publicType.getBasicType() == EbtStruct)
Jamie Madillb98c3a82015-07-23 14:26:04 -04001262 {
1263 error(identifierLocation, "cannot be used with a structure",
1264 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +03001265 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001266 }
Jiajia Qinbc585152017-06-23 15:42:17 +08001267 break;
1268 case EvqBuffer:
1269 if (publicType.getBasicType() != EbtInterfaceBlock)
1270 {
1271 error(identifierLocation,
1272 "cannot declare buffer variables at global scope(outside a block)",
1273 getQualifierString(publicType.qualifier));
1274 return;
1275 }
1276 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001277 default:
1278 break;
Olli Etuahofa33d582015-04-09 14:33:12 +03001279 }
jchen10cc2a10e2017-05-03 14:05:12 +08001280 std::string reason(getBasicString(publicType.getBasicType()));
1281 reason += "s must be uniform";
Jamie Madillb98c3a82015-07-23 14:26:04 -04001282 if (publicType.qualifier != EvqUniform &&
jchen10cc2a10e2017-05-03 14:05:12 +08001283 !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str()))
Martin Radev2cc85b32016-08-05 16:22:53 +03001284 {
1285 return;
1286 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001287
Andrei Volykhina5527072017-03-22 16:46:30 +03001288 if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal &&
1289 publicType.qualifier != EvqConst) &&
1290 publicType.getBasicType() == EbtYuvCscStandardEXT)
1291 {
1292 error(identifierLocation, "cannot be used with a yuvCscStandardEXT",
1293 getQualifierString(publicType.qualifier));
1294 return;
1295 }
1296
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001297 if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform)
1298 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001299 // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized.
1300 // But invalid shaders may still reach here with an unsized array declaration.
1301 if (!publicType.isUnsizedArray())
1302 {
1303 TType type(publicType);
1304 checkUniformLocationInRange(identifierLocation, type.getLocationCount(),
1305 publicType.layoutQualifier);
1306 }
1307 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001308
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001309 // check for layout qualifier issues
1310 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
Andrei Volykhina5527072017-03-22 16:46:30 +03001311
Martin Radev2cc85b32016-08-05 16:22:53 +03001312 if (IsImage(publicType.getBasicType()))
1313 {
1314
1315 switch (layoutQualifier.imageInternalFormat)
1316 {
1317 case EiifRGBA32F:
1318 case EiifRGBA16F:
1319 case EiifR32F:
1320 case EiifRGBA8:
1321 case EiifRGBA8_SNORM:
1322 if (!IsFloatImage(publicType.getBasicType()))
1323 {
1324 error(identifierLocation,
1325 "internal image format requires a floating image type",
1326 getBasicString(publicType.getBasicType()));
1327 return;
1328 }
1329 break;
1330 case EiifRGBA32I:
1331 case EiifRGBA16I:
1332 case EiifRGBA8I:
1333 case EiifR32I:
1334 if (!IsIntegerImage(publicType.getBasicType()))
1335 {
1336 error(identifierLocation,
1337 "internal image format requires an integer image type",
1338 getBasicString(publicType.getBasicType()));
1339 return;
1340 }
1341 break;
1342 case EiifRGBA32UI:
1343 case EiifRGBA16UI:
1344 case EiifRGBA8UI:
1345 case EiifR32UI:
1346 if (!IsUnsignedImage(publicType.getBasicType()))
1347 {
1348 error(identifierLocation,
1349 "internal image format requires an unsigned image type",
1350 getBasicString(publicType.getBasicType()));
1351 return;
1352 }
1353 break;
1354 case EiifUnspecified:
1355 error(identifierLocation, "layout qualifier", "No image internal format specified");
1356 return;
1357 default:
1358 error(identifierLocation, "layout qualifier", "unrecognized token");
1359 return;
1360 }
1361
1362 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
1363 switch (layoutQualifier.imageInternalFormat)
1364 {
1365 case EiifR32F:
1366 case EiifR32I:
1367 case EiifR32UI:
1368 break;
1369 default:
1370 if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
1371 {
1372 error(identifierLocation, "layout qualifier",
1373 "Except for images with the r32f, r32i and r32ui format qualifiers, "
1374 "image variables must be qualified readonly and/or writeonly");
1375 return;
1376 }
1377 break;
1378 }
1379 }
1380 else
1381 {
Olli Etuaho43364892017-02-13 16:00:12 +00001382 checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat);
Olli Etuaho43364892017-02-13 16:00:12 +00001383 checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
1384 }
jchen104cdac9e2017-05-08 11:01:20 +08001385
1386 if (IsAtomicCounter(publicType.getBasicType()))
1387 {
1388 atomicCounterQualifierErrorCheck(publicType, identifierLocation);
1389 }
1390 else
1391 {
1392 checkOffsetIsNotSpecified(identifierLocation, layoutQualifier.offset);
1393 }
Olli Etuaho43364892017-02-13 16:00:12 +00001394}
Martin Radev2cc85b32016-08-05 16:22:53 +03001395
Olli Etuaho43364892017-02-13 16:00:12 +00001396void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type)
1397{
1398 TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001399 // Note that the ESSL 3.10 section 4.4.5 is not particularly clear on how the binding qualifier
1400 // on arrays of arrays should be handled. We interpret the spec so that the binding value is
1401 // incremented for each element of the innermost nested arrays. This is in line with how arrays
1402 // of arrays of blocks are specified to behave in GLSL 4.50 and a conservative interpretation
1403 // when it comes to which shaders are accepted by the compiler.
1404 int arrayTotalElementCount = type.getArraySizeProduct();
Olli Etuaho43364892017-02-13 16:00:12 +00001405 if (IsImage(type.getBasicType()))
1406 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001407 checkImageBindingIsValid(identifierLocation, layoutQualifier.binding,
1408 arrayTotalElementCount);
Olli Etuaho43364892017-02-13 16:00:12 +00001409 }
1410 else if (IsSampler(type.getBasicType()))
1411 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001412 checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding,
1413 arrayTotalElementCount);
Olli Etuaho43364892017-02-13 16:00:12 +00001414 }
jchen104cdac9e2017-05-08 11:01:20 +08001415 else if (IsAtomicCounter(type.getBasicType()))
1416 {
1417 checkAtomicCounterBindingIsValid(identifierLocation, layoutQualifier.binding);
1418 }
Olli Etuaho43364892017-02-13 16:00:12 +00001419 else
1420 {
1421 ASSERT(!IsOpaqueType(type.getBasicType()));
1422 checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
Martin Radev2cc85b32016-08-05 16:22:53 +03001423 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001424}
1425
Olli Etuaho856c4972016-08-08 11:38:39 +03001426void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1427 const TString &layoutQualifierName,
1428 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001429{
1430
1431 if (mShaderVersion < versionRequired)
1432 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001433 error(location, "invalid layout qualifier: not supported", layoutQualifierName.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03001434 }
1435}
1436
Olli Etuaho856c4972016-08-08 11:38:39 +03001437bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1438 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001439{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001440 const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
Martin Radev802abe02016-08-04 17:48:32 +03001441 for (size_t i = 0u; i < localSize.size(); ++i)
1442 {
1443 if (localSize[i] != -1)
1444 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001445 error(location,
1446 "invalid layout qualifier: only valid when used with 'in' in a compute shader "
1447 "global layout declaration",
1448 getWorkGroupSizeString(i));
Olli Etuaho8a176262016-08-16 14:23:01 +03001449 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001450 }
1451 }
1452
Olli Etuaho8a176262016-08-16 14:23:01 +03001453 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001454}
1455
Olli Etuaho43364892017-02-13 16:00:12 +00001456void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
Martin Radev2cc85b32016-08-05 16:22:53 +03001457 TLayoutImageInternalFormat internalFormat)
1458{
1459 if (internalFormat != EiifUnspecified)
1460 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001461 error(location, "invalid layout qualifier: only valid when used with images",
1462 getImageInternalFormatString(internalFormat));
Martin Radev2cc85b32016-08-05 16:22:53 +03001463 }
Olli Etuaho43364892017-02-13 16:00:12 +00001464}
1465
1466void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
1467{
1468 if (binding != -1)
1469 {
1470 error(location,
1471 "invalid layout qualifier: only valid when used with opaque types or blocks",
1472 "binding");
1473 }
1474}
1475
jchen104cdac9e2017-05-08 11:01:20 +08001476void TParseContext::checkOffsetIsNotSpecified(const TSourceLoc &location, int offset)
1477{
1478 if (offset != -1)
1479 {
1480 error(location, "invalid layout qualifier: only valid when used with atomic counters",
1481 "offset");
1482 }
1483}
1484
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001485void TParseContext::checkImageBindingIsValid(const TSourceLoc &location,
1486 int binding,
1487 int arrayTotalElementCount)
Olli Etuaho43364892017-02-13 16:00:12 +00001488{
1489 // Expects arraySize to be 1 when setting binding for only a single variable.
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001490 if (binding >= 0 && binding + arrayTotalElementCount > mMaxImageUnits)
Olli Etuaho43364892017-02-13 16:00:12 +00001491 {
1492 error(location, "image binding greater than gl_MaxImageUnits", "binding");
1493 }
1494}
1495
1496void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location,
1497 int binding,
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001498 int arrayTotalElementCount)
Olli Etuaho43364892017-02-13 16:00:12 +00001499{
1500 // Expects arraySize to be 1 when setting binding for only a single variable.
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001501 if (binding >= 0 && binding + arrayTotalElementCount > mMaxCombinedTextureImageUnits)
Olli Etuaho43364892017-02-13 16:00:12 +00001502 {
1503 error(location, "sampler binding greater than maximum texture units", "binding");
1504 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001505}
1506
Jiajia Qinbc585152017-06-23 15:42:17 +08001507void TParseContext::checkBlockBindingIsValid(const TSourceLoc &location,
1508 const TQualifier &qualifier,
1509 int binding,
1510 int arraySize)
jchen10af713a22017-04-19 09:10:56 +08001511{
1512 int size = (arraySize == 0 ? 1 : arraySize);
Jiajia Qinbc585152017-06-23 15:42:17 +08001513 if (qualifier == EvqUniform)
jchen10af713a22017-04-19 09:10:56 +08001514 {
Jiajia Qinbc585152017-06-23 15:42:17 +08001515 if (binding + size > mMaxUniformBufferBindings)
1516 {
1517 error(location, "uniform block binding greater than MAX_UNIFORM_BUFFER_BINDINGS",
1518 "binding");
1519 }
1520 }
1521 else if (qualifier == EvqBuffer)
1522 {
1523 if (binding + size > mMaxShaderStorageBufferBindings)
1524 {
1525 error(location,
1526 "shader storage block binding greater than MAX_SHADER_STORAGE_BUFFER_BINDINGS",
1527 "binding");
1528 }
jchen10af713a22017-04-19 09:10:56 +08001529 }
1530}
jchen104cdac9e2017-05-08 11:01:20 +08001531void TParseContext::checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding)
1532{
1533 if (binding >= mMaxAtomicCounterBindings)
1534 {
1535 error(location, "atomic counter binding greater than gl_MaxAtomicCounterBindings",
1536 "binding");
1537 }
1538}
jchen10af713a22017-04-19 09:10:56 +08001539
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001540void TParseContext::checkUniformLocationInRange(const TSourceLoc &location,
1541 int objectLocationCount,
1542 const TLayoutQualifier &layoutQualifier)
1543{
1544 int loc = layoutQualifier.location;
1545 if (loc >= 0 && loc + objectLocationCount > mMaxUniformLocations)
1546 {
1547 error(location, "Uniform location out of range", "location");
1548 }
1549}
1550
Andrei Volykhina5527072017-03-22 16:46:30 +03001551void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv)
1552{
1553 if (yuv != false)
1554 {
1555 error(location, "invalid layout qualifier: only valid on program outputs", "yuv");
1556 }
1557}
1558
Jiajia Qinbc585152017-06-23 15:42:17 +08001559void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandidate,
1560 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001561{
1562 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1563 {
1564 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
Jiajia Qinbc585152017-06-23 15:42:17 +08001565 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
1566 if (!IsImage(argument->getBasicType()) && (IsQualifierUnspecified(qual) || qual == EvqIn ||
1567 qual == EvqInOut || qual == EvqConstReadOnly))
1568 {
1569 if (argument->getMemoryQualifier().writeonly)
1570 {
1571 error(argument->getLine(),
1572 "Writeonly value cannot be passed for 'in' or 'inout' parameters.",
1573 fnCall->getFunctionSymbolInfo()->getName().c_str());
1574 return;
1575 }
1576 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001577 if (qual == EvqOut || qual == EvqInOut)
1578 {
Olli Etuaho8a176262016-08-16 14:23:01 +03001579 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001580 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001581 error(argument->getLine(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00001582 "Constant value cannot be passed for 'out' or 'inout' parameters.",
Olli Etuahoec9232b2017-03-27 17:01:37 +03001583 fnCall->getFunctionSymbolInfo()->getName().c_str());
Olli Etuaho383b7912016-08-05 11:22:59 +03001584 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001585 }
1586 }
1587 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001588}
1589
Martin Radev70866b82016-07-22 15:27:42 +03001590void TParseContext::checkInvariantVariableQualifier(bool invariant,
1591 const TQualifier qualifier,
1592 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001593{
Martin Radev70866b82016-07-22 15:27:42 +03001594 if (!invariant)
1595 return;
1596
1597 if (mShaderVersion < 300)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001598 {
Martin Radev70866b82016-07-22 15:27:42 +03001599 // input variables in the fragment shader can be also qualified as invariant
1600 if (!sh::CanBeInvariantESSL1(qualifier))
1601 {
1602 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1603 }
1604 }
1605 else
1606 {
1607 if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
1608 {
1609 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1610 }
Olli Etuaho37ad4742015-04-27 13:18:50 +03001611 }
1612}
1613
Arun Patole7e7e68d2015-05-22 12:02:25 +05301614bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001615{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001616 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001617 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1618 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001619}
1620
Arun Patole7e7e68d2015-05-22 12:02:25 +05301621bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001622{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001623 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001624}
1625
Jamie Madillb98c3a82015-07-23 14:26:04 -04001626void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1627 const char *extName,
1628 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001629{
1630 pp::SourceLocation srcLoc;
1631 srcLoc.file = loc.first_file;
1632 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001633 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001634}
1635
Jamie Madillb98c3a82015-07-23 14:26:04 -04001636void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1637 const char *name,
1638 const char *value,
1639 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001640{
1641 pp::SourceLocation srcLoc;
1642 srcLoc.file = loc.first_file;
1643 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001644 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001645}
1646
Martin Radev4c4c8e72016-08-04 12:25:34 +03001647sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
Martin Radev802abe02016-08-04 17:48:32 +03001648{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001649 sh::WorkGroupSize result;
Martin Radev802abe02016-08-04 17:48:32 +03001650 for (size_t i = 0u; i < result.size(); ++i)
1651 {
1652 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1653 {
1654 result[i] = 1;
1655 }
1656 else
1657 {
1658 result[i] = mComputeShaderLocalSize[i];
1659 }
1660 }
1661 return result;
1662}
1663
Olli Etuaho56229f12017-07-10 14:16:33 +03001664TIntermConstantUnion *TParseContext::addScalarLiteral(const TConstantUnion *constantUnion,
1665 const TSourceLoc &line)
1666{
1667 TIntermConstantUnion *node = new TIntermConstantUnion(
1668 constantUnion, TType(constantUnion->getType(), EbpUndefined, EvqConst));
1669 node->setLine(line);
1670 return node;
1671}
1672
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001673/////////////////////////////////////////////////////////////////////////////////
1674//
1675// Non-Errors.
1676//
1677/////////////////////////////////////////////////////////////////////////////////
1678
Jamie Madill5c097022014-08-20 16:38:32 -04001679const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1680 const TString *name,
1681 const TSymbol *symbol)
1682{
Jamie Madill5c097022014-08-20 16:38:32 -04001683 if (!symbol)
1684 {
1685 error(location, "undeclared identifier", name->c_str());
Olli Etuaho0f684632017-07-13 12:42:15 +03001686 return nullptr;
Jamie Madill5c097022014-08-20 16:38:32 -04001687 }
Olli Etuaho0f684632017-07-13 12:42:15 +03001688
1689 if (!symbol->isVariable())
Jamie Madill5c097022014-08-20 16:38:32 -04001690 {
1691 error(location, "variable expected", name->c_str());
Olli Etuaho0f684632017-07-13 12:42:15 +03001692 return nullptr;
Jamie Madill5c097022014-08-20 16:38:32 -04001693 }
Olli Etuaho0f684632017-07-13 12:42:15 +03001694
1695 const TVariable *variable = static_cast<const TVariable *>(symbol);
1696
1697 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
1698 !variable->getExtension().empty())
Jamie Madill5c097022014-08-20 16:38:32 -04001699 {
Olli Etuaho0f684632017-07-13 12:42:15 +03001700 checkCanUseExtension(location, variable->getExtension());
Jamie Madill5c097022014-08-20 16:38:32 -04001701 }
1702
Olli Etuaho0f684632017-07-13 12:42:15 +03001703 // Reject shaders using both gl_FragData and gl_FragColor
1704 TQualifier qualifier = variable->getType().getQualifier();
1705 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill5c097022014-08-20 16:38:32 -04001706 {
Olli Etuaho0f684632017-07-13 12:42:15 +03001707 mUsesFragData = true;
1708 }
1709 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
1710 {
1711 mUsesFragColor = true;
1712 }
1713 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1714 {
1715 mUsesSecondaryOutputs = true;
Jamie Madill5c097022014-08-20 16:38:32 -04001716 }
1717
Olli Etuaho0f684632017-07-13 12:42:15 +03001718 // This validation is not quite correct - it's only an error to write to
1719 // both FragData and FragColor. For simplicity, and because users shouldn't
1720 // be rewarded for reading from undefined varaibles, return an error
1721 // if they are both referenced, rather than assigned.
1722 if (mUsesFragData && mUsesFragColor)
1723 {
1724 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1725 if (mUsesSecondaryOutputs)
1726 {
1727 errorMessage =
1728 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1729 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1730 }
1731 error(location, errorMessage, name->c_str());
1732 }
1733
1734 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1735 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1736 qualifier == EvqWorkGroupSize)
1737 {
1738 error(location,
1739 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1740 "gl_WorkGroupSize");
1741 }
Jamie Madill5c097022014-08-20 16:38:32 -04001742 return variable;
1743}
1744
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001745TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1746 const TString *name,
1747 const TSymbol *symbol)
1748{
1749 const TVariable *variable = getNamedVariable(location, name, symbol);
1750
Olli Etuaho0f684632017-07-13 12:42:15 +03001751 if (!variable)
1752 {
1753 TIntermTyped *node = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
1754 node->setLine(location);
1755 return node;
1756 }
1757
Olli Etuaho09b04a22016-12-15 13:30:26 +00001758 if (variable->getType().getQualifier() == EvqViewIDOVR && IsWebGLBasedSpec(mShaderSpec) &&
1759 mShaderType == GL_FRAGMENT_SHADER && !isExtensionEnabled("GL_OVR_multiview2"))
1760 {
1761 // WEBGL_multiview spec
1762 error(location, "Need to enable OVR_multiview2 to use gl_ViewID_OVR in fragment shader",
1763 "gl_ViewID_OVR");
1764 }
1765
Olli Etuaho56229f12017-07-10 14:16:33 +03001766 TIntermTyped *node = nullptr;
1767
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001768 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001769 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001770 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho56229f12017-07-10 14:16:33 +03001771 node = new TIntermConstantUnion(constArray, variable->getType());
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001772 }
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001773 else if (variable->getType().getQualifier() == EvqWorkGroupSize &&
1774 mComputeShaderLocalSizeDeclared)
1775 {
1776 // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
1777 // needs to be added to the AST as a constant and not as a symbol.
1778 sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
1779 TConstantUnion *constArray = new TConstantUnion[3];
1780 for (size_t i = 0; i < 3; ++i)
1781 {
1782 constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
1783 }
1784
1785 ASSERT(variable->getType().getBasicType() == EbtUInt);
1786 ASSERT(variable->getType().getObjectSize() == 3);
1787
1788 TType type(variable->getType());
1789 type.setQualifier(EvqConst);
Olli Etuaho56229f12017-07-10 14:16:33 +03001790 node = new TIntermConstantUnion(constArray, type);
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001791 }
Jiawei Shaod8105a02017-08-08 09:54:36 +08001792 // TODO(jiawei.shao@intel.com): set array sizes for user-defined geometry shader inputs.
1793 else if (variable->getType().getQualifier() == EvqPerVertexIn)
1794 {
1795 TType type(variable->getType());
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001796 type.setArraySize(0, mGeometryShaderInputArraySize);
Jiawei Shaod8105a02017-08-08 09:54:36 +08001797 node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), type);
1798 }
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001799 else
1800 {
Olli Etuaho56229f12017-07-10 14:16:33 +03001801 node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), variable->getType());
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001802 }
Olli Etuaho56229f12017-07-10 14:16:33 +03001803 ASSERT(node != nullptr);
1804 node->setLine(location);
1805 return node;
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001806}
1807
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001808// Initializers show up in several places in the grammar. Have one set of
1809// code to handle them here.
1810//
Olli Etuaho914b79a2017-06-19 16:03:19 +03001811// Returns true on success.
Jamie Madillb98c3a82015-07-23 14:26:04 -04001812bool TParseContext::executeInitializer(const TSourceLoc &line,
1813 const TString &identifier,
1814 const TPublicType &pType,
1815 TIntermTyped *initializer,
Olli Etuaho13389b62016-10-16 11:48:18 +01001816 TIntermBinary **initNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001817{
Olli Etuaho13389b62016-10-16 11:48:18 +01001818 ASSERT(initNode != nullptr);
1819 ASSERT(*initNode == nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001820 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001821
Olli Etuaho2935c582015-04-08 14:32:06 +03001822 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001823 if (type.isUnsizedArray())
1824 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001825 // In case initializer is not an array or type has more dimensions than initializer, this
1826 // will default to setting array sizes to 1. We have not checked yet whether the initializer
1827 // actually is an array or not. Having a non-array initializer for an unsized array will
1828 // result in an error later, so we don't generate an error message here.
1829 type.sizeUnsizedArrays(initializer->getType().getArraySizes());
Olli Etuaho376f1b52015-04-13 13:23:41 +03001830 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001831 if (!declareVariable(line, identifier, type, &variable))
1832 {
Olli Etuaho914b79a2017-06-19 16:03:19 +03001833 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001834 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001835
Olli Etuahob0c645e2015-05-12 14:25:36 +03001836 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001837 if (symbolTable.atGlobalLevel() &&
1838 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001839 {
1840 // Error message does not completely match behavior with ESSL 1.00, but
1841 // we want to steer developers towards only using constant expressions.
1842 error(line, "global variable initializers must be constant expressions", "=");
Olli Etuaho914b79a2017-06-19 16:03:19 +03001843 return false;
Olli Etuahob0c645e2015-05-12 14:25:36 +03001844 }
1845 if (globalInitWarning)
1846 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001847 warning(
1848 line,
1849 "global variable initializers should be constant expressions "
1850 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1851 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001852 }
1853
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001854 //
1855 // identifier must be of type constant, a global, or a temporary
1856 //
1857 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301858 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1859 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001860 error(line, " cannot initialize this type of qualifier ",
1861 variable->getType().getQualifierString());
Olli Etuaho914b79a2017-06-19 16:03:19 +03001862 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001863 }
1864 //
1865 // test for and propagate constant
1866 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001867
Arun Patole7e7e68d2015-05-22 12:02:25 +05301868 if (qualifier == EvqConst)
1869 {
1870 if (qualifier != initializer->getType().getQualifier())
1871 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001872 std::stringstream reasonStream;
1873 reasonStream << "assigning non-constant to '" << variable->getType().getCompleteString()
1874 << "'";
1875 std::string reason = reasonStream.str();
1876 error(line, reason.c_str(), "=");
alokp@chromium.org58e54292010-08-24 21:40:03 +00001877 variable->getType().setQualifier(EvqTemporary);
Olli Etuaho914b79a2017-06-19 16:03:19 +03001878 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001879 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301880 if (type != initializer->getType())
1881 {
1882 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001883 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001884 variable->getType().setQualifier(EvqTemporary);
Olli Etuaho914b79a2017-06-19 16:03:19 +03001885 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001886 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001887
1888 // Save the constant folded value to the variable if possible. For example array
1889 // initializers are not folded, since that way copying the array literal to multiple places
1890 // in the shader is avoided.
1891 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1892 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301893 if (initializer->getAsConstantUnion())
1894 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001895 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuaho914b79a2017-06-19 16:03:19 +03001896 ASSERT(*initNode == nullptr);
1897 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301898 }
1899 else if (initializer->getAsSymbolNode())
1900 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001901 const TSymbol *symbol =
1902 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1903 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001904
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001905 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001906 if (constArray)
1907 {
1908 variable->shareConstPointer(constArray);
Olli Etuaho914b79a2017-06-19 16:03:19 +03001909 ASSERT(*initNode == nullptr);
1910 return true;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001911 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001912 }
1913 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001914
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03001915 TIntermSymbol *intermSymbol =
1916 new TIntermSymbol(variable->getUniqueId(), variable->getName(), variable->getType());
1917 intermSymbol->setLine(line);
Olli Etuaho13389b62016-10-16 11:48:18 +01001918 *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1919 if (*initNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001920 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001921 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
Olli Etuaho914b79a2017-06-19 16:03:19 +03001922 return false;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001923 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001924
Olli Etuaho914b79a2017-06-19 16:03:19 +03001925 return true;
1926}
1927
1928TIntermNode *TParseContext::addConditionInitializer(const TPublicType &pType,
1929 const TString &identifier,
1930 TIntermTyped *initializer,
1931 const TSourceLoc &loc)
1932{
1933 checkIsScalarBool(loc, pType);
1934 TIntermBinary *initNode = nullptr;
1935 if (executeInitializer(loc, identifier, pType, initializer, &initNode))
1936 {
1937 // The initializer is valid. The init condition needs to have a node - either the
1938 // initializer node, or a constant node in case the initialized variable is const and won't
1939 // be recorded in the AST.
1940 if (initNode == nullptr)
1941 {
1942 return initializer;
1943 }
1944 else
1945 {
1946 TIntermDeclaration *declaration = new TIntermDeclaration();
1947 declaration->appendDeclarator(initNode);
1948 return declaration;
1949 }
1950 }
1951 return nullptr;
1952}
1953
1954TIntermNode *TParseContext::addLoop(TLoopType type,
1955 TIntermNode *init,
1956 TIntermNode *cond,
1957 TIntermTyped *expr,
1958 TIntermNode *body,
1959 const TSourceLoc &line)
1960{
1961 TIntermNode *node = nullptr;
1962 TIntermTyped *typedCond = nullptr;
1963 if (cond)
1964 {
1965 typedCond = cond->getAsTyped();
1966 }
1967 if (cond == nullptr || typedCond)
1968 {
Olli Etuahocce89652017-06-19 16:04:09 +03001969 if (type == ELoopDoWhile)
1970 {
1971 checkIsScalarBool(line, typedCond);
1972 }
1973 // In the case of other loops, it was checked before that the condition is a scalar boolean.
1974 ASSERT(mDiagnostics->numErrors() > 0 || typedCond == nullptr ||
1975 (typedCond->getBasicType() == EbtBool && !typedCond->isArray() &&
1976 !typedCond->isVector()));
1977
Olli Etuaho3ec75682017-07-05 17:02:55 +03001978 node = new TIntermLoop(type, init, typedCond, expr, EnsureBlock(body));
Olli Etuaho914b79a2017-06-19 16:03:19 +03001979 node->setLine(line);
1980 return node;
1981 }
1982
Olli Etuahocce89652017-06-19 16:04:09 +03001983 ASSERT(type != ELoopDoWhile);
1984
Olli Etuaho914b79a2017-06-19 16:03:19 +03001985 TIntermDeclaration *declaration = cond->getAsDeclarationNode();
1986 ASSERT(declaration);
1987 TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode();
1988 ASSERT(declarator->getLeft()->getAsSymbolNode());
1989
1990 // The condition is a declaration. In the AST representation we don't support declarations as
1991 // loop conditions. Wrap the loop to a block that declares the condition variable and contains
1992 // the loop.
1993 TIntermBlock *block = new TIntermBlock();
1994
1995 TIntermDeclaration *declareCondition = new TIntermDeclaration();
1996 declareCondition->appendDeclarator(declarator->getLeft()->deepCopy());
1997 block->appendStatement(declareCondition);
1998
1999 TIntermBinary *conditionInit = new TIntermBinary(EOpAssign, declarator->getLeft()->deepCopy(),
2000 declarator->getRight()->deepCopy());
Olli Etuaho3ec75682017-07-05 17:02:55 +03002001 TIntermLoop *loop = new TIntermLoop(type, init, conditionInit, expr, EnsureBlock(body));
Olli Etuaho914b79a2017-06-19 16:03:19 +03002002 block->appendStatement(loop);
2003 loop->setLine(line);
2004 block->setLine(line);
2005 return block;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002006}
2007
Olli Etuahocce89652017-06-19 16:04:09 +03002008TIntermNode *TParseContext::addIfElse(TIntermTyped *cond,
2009 TIntermNodePair code,
2010 const TSourceLoc &loc)
2011{
Olli Etuaho56229f12017-07-10 14:16:33 +03002012 bool isScalarBool = checkIsScalarBool(loc, cond);
Olli Etuahocce89652017-06-19 16:04:09 +03002013
2014 // For compile time constant conditions, prune the code now.
Olli Etuaho56229f12017-07-10 14:16:33 +03002015 if (isScalarBool && cond->getAsConstantUnion())
Olli Etuahocce89652017-06-19 16:04:09 +03002016 {
2017 if (cond->getAsConstantUnion()->getBConst(0) == true)
2018 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03002019 return EnsureBlock(code.node1);
Olli Etuahocce89652017-06-19 16:04:09 +03002020 }
2021 else
2022 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03002023 return EnsureBlock(code.node2);
Olli Etuahocce89652017-06-19 16:04:09 +03002024 }
2025 }
2026
Olli Etuaho3ec75682017-07-05 17:02:55 +03002027 TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2));
Olli Etuahocce89652017-06-19 16:04:09 +03002028 node->setLine(loc);
2029
2030 return node;
2031}
2032
Olli Etuaho0e3aee32016-10-27 12:56:38 +01002033void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
2034{
2035 checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
2036 typeSpecifier->getBasicType());
2037
2038 if (mShaderVersion < 300 && typeSpecifier->array)
2039 {
2040 error(typeSpecifier->getLine(), "not supported", "first-class array");
2041 typeSpecifier->clearArrayness();
2042 }
2043}
2044
Martin Radev70866b82016-07-22 15:27:42 +03002045TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302046 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002047{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002048 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002049
Martin Radev70866b82016-07-22 15:27:42 +03002050 TPublicType returnType = typeSpecifier;
2051 returnType.qualifier = typeQualifier.qualifier;
2052 returnType.invariant = typeQualifier.invariant;
2053 returnType.layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03002054 returnType.memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03002055 returnType.precision = typeSpecifier.precision;
2056
2057 if (typeQualifier.precision != EbpUndefined)
2058 {
2059 returnType.precision = typeQualifier.precision;
2060 }
2061
Martin Radev4a9cd802016-09-01 16:51:51 +03002062 checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
2063 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03002064
Martin Radev4a9cd802016-09-01 16:51:51 +03002065 checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
2066 typeSpecifier.getLine());
Martin Radev70866b82016-07-22 15:27:42 +03002067
Martin Radev4a9cd802016-09-01 16:51:51 +03002068 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002069
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002070 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002071 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03002072 if (typeSpecifier.array)
2073 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002074 error(typeSpecifier.getLine(), "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03002075 returnType.clearArrayness();
2076 }
2077
Martin Radev70866b82016-07-22 15:27:42 +03002078 if (returnType.qualifier == EvqAttribute &&
Martin Radev4a9cd802016-09-01 16:51:51 +03002079 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002080 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002081 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03002082 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002083 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002084
Martin Radev70866b82016-07-22 15:27:42 +03002085 if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
Martin Radev4a9cd802016-09-01 16:51:51 +03002086 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002087 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002088 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03002089 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002090 }
2091 }
2092 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002093 {
Martin Radev70866b82016-07-22 15:27:42 +03002094 if (!returnType.layoutQualifier.isEmpty())
Olli Etuahoabb0c382015-07-13 12:01:12 +03002095 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002096 checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03002097 }
Martin Radev70866b82016-07-22 15:27:42 +03002098 if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
2099 returnType.qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002100 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002101 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
2102 typeSpecifier.getLine());
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002103 }
Martin Radev70866b82016-07-22 15:27:42 +03002104 if (returnType.qualifier == EvqComputeIn)
Martin Radev802abe02016-08-04 17:48:32 +03002105 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002106 error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
Martin Radev802abe02016-08-04 17:48:32 +03002107 "in");
Martin Radev802abe02016-08-04 17:48:32 +03002108 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002109 }
2110
2111 return returnType;
2112}
2113
Olli Etuaho856c4972016-08-08 11:38:39 +03002114void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
2115 const TPublicType &type,
2116 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03002117{
2118 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
Martin Radev4a9cd802016-09-01 16:51:51 +03002119 if (type.getBasicType() == EbtBool)
Olli Etuahocc36b982015-07-10 14:14:18 +03002120 {
2121 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002122 }
2123
2124 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
2125 switch (qualifier)
2126 {
2127 case EvqVertexIn:
2128 // ESSL 3.00 section 4.3.4
2129 if (type.array)
2130 {
2131 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002132 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002133 // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03002134 return;
2135 case EvqFragmentOut:
2136 // ESSL 3.00 section 4.3.6
Martin Radev4a9cd802016-09-01 16:51:51 +03002137 if (type.typeSpecifierNonArray.isMatrix())
Olli Etuahocc36b982015-07-10 14:14:18 +03002138 {
2139 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002140 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002141 // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03002142 return;
2143 default:
2144 break;
2145 }
2146
2147 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
2148 // restrictions.
2149 bool typeContainsIntegers =
Martin Radev4a9cd802016-09-01 16:51:51 +03002150 (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
2151 type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
Olli Etuahocc36b982015-07-10 14:14:18 +03002152 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
2153 {
2154 error(qualifierLocation, "must use 'flat' interpolation here",
2155 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002156 }
2157
Martin Radev4a9cd802016-09-01 16:51:51 +03002158 if (type.getBasicType() == EbtStruct)
Olli Etuahocc36b982015-07-10 14:14:18 +03002159 {
2160 // ESSL 3.00 sections 4.3.4 and 4.3.6.
2161 // These restrictions are only implied by the ESSL 3.00 spec, but
2162 // the ESSL 3.10 spec lists these restrictions explicitly.
2163 if (type.array)
2164 {
2165 error(qualifierLocation, "cannot be an array of structures",
2166 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002167 }
2168 if (type.isStructureContainingArrays())
2169 {
2170 error(qualifierLocation, "cannot be a structure containing an array",
2171 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002172 }
2173 if (type.isStructureContainingType(EbtStruct))
2174 {
2175 error(qualifierLocation, "cannot be a structure containing a structure",
2176 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002177 }
2178 if (type.isStructureContainingType(EbtBool))
2179 {
2180 error(qualifierLocation, "cannot be a structure containing a bool",
2181 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002182 }
2183 }
2184}
2185
Martin Radev2cc85b32016-08-05 16:22:53 +03002186void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
2187{
2188 if (qualifier.getType() == QtStorage)
2189 {
2190 const TStorageQualifierWrapper &storageQualifier =
2191 static_cast<const TStorageQualifierWrapper &>(qualifier);
2192 if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
2193 !symbolTable.atGlobalLevel())
2194 {
2195 error(storageQualifier.getLine(),
2196 "Local variables can only use the const storage qualifier.",
2197 storageQualifier.getQualifierString().c_str());
2198 }
2199 }
2200}
2201
Olli Etuaho43364892017-02-13 16:00:12 +00002202void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
Martin Radev2cc85b32016-08-05 16:22:53 +03002203 const TSourceLoc &location)
2204{
Jiajia Qinbc585152017-06-23 15:42:17 +08002205 const std::string reason(
2206 "Only allowed with shader storage blocks, variables declared within shader storage blocks "
2207 "and variables declared as image types.");
Martin Radev2cc85b32016-08-05 16:22:53 +03002208 if (memoryQualifier.readonly)
2209 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002210 error(location, reason.c_str(), "readonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03002211 }
2212 if (memoryQualifier.writeonly)
2213 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002214 error(location, reason.c_str(), "writeonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03002215 }
Martin Radev049edfa2016-11-11 14:35:37 +02002216 if (memoryQualifier.coherent)
2217 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002218 error(location, reason.c_str(), "coherent");
Martin Radev049edfa2016-11-11 14:35:37 +02002219 }
2220 if (memoryQualifier.restrictQualifier)
2221 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002222 error(location, reason.c_str(), "restrict");
Martin Radev049edfa2016-11-11 14:35:37 +02002223 }
2224 if (memoryQualifier.volatileQualifier)
2225 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002226 error(location, reason.c_str(), "volatile");
Martin Radev049edfa2016-11-11 14:35:37 +02002227 }
Martin Radev2cc85b32016-08-05 16:22:53 +03002228}
2229
jchen104cdac9e2017-05-08 11:01:20 +08002230// Make sure there is no offset overlapping, and store the newly assigned offset to "type" in
2231// intermediate tree.
2232void TParseContext::checkAtomicCounterOffsetIsNotOverlapped(TPublicType &publicType,
2233 size_t size,
2234 bool forceAppend,
2235 const TSourceLoc &loc,
2236 TType &type)
2237{
2238 auto &bindingState = mAtomicCounterBindingStates[publicType.layoutQualifier.binding];
2239 int offset;
2240 if (publicType.layoutQualifier.offset == -1 || forceAppend)
2241 {
2242 offset = bindingState.appendSpan(size);
2243 }
2244 else
2245 {
2246 offset = bindingState.insertSpan(publicType.layoutQualifier.offset, size);
2247 }
2248 if (offset == -1)
2249 {
2250 error(loc, "Offset overlapping", "atomic counter");
2251 return;
2252 }
2253 TLayoutQualifier qualifier = type.getLayoutQualifier();
2254 qualifier.offset = offset;
2255 type.setLayoutQualifier(qualifier);
2256}
2257
Olli Etuaho13389b62016-10-16 11:48:18 +01002258TIntermDeclaration *TParseContext::parseSingleDeclaration(
2259 TPublicType &publicType,
2260 const TSourceLoc &identifierOrTypeLocation,
2261 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04002262{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07002263 TType type(publicType);
2264 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
2265 mDirectiveHandler.pragma().stdgl.invariantAll)
2266 {
2267 TQualifier qualifier = type.getQualifier();
2268
2269 // The directive handler has already taken care of rejecting invalid uses of this pragma
2270 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
2271 // affected variable declarations:
2272 //
2273 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
2274 // elsewhere, in TranslatorGLSL.)
2275 //
2276 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
2277 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
2278 // the way this is currently implemented we have to enable this compiler option before
2279 // parsing the shader and determining the shading language version it uses. If this were
2280 // implemented as a post-pass, the workaround could be more targeted.
2281 //
2282 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
2283 // the specification, but there are desktop OpenGL drivers that expect that this is the
2284 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
2285 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
2286 {
2287 type.setInvariant(true);
2288 }
2289 }
2290
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002291 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2292 identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002293
Olli Etuahobab4c082015-04-24 16:38:49 +03002294 bool emptyDeclaration = (identifier == "");
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002295 mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration;
Olli Etuahofa33d582015-04-09 14:33:12 +03002296
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002297 TIntermSymbol *symbol = nullptr;
Olli Etuahobab4c082015-04-24 16:38:49 +03002298 if (emptyDeclaration)
2299 {
Martin Radevb8b01222016-11-20 23:25:53 +02002300 emptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002301 // In most cases we don't need to create a symbol node for an empty declaration.
2302 // But if the empty declaration is declaring a struct type, the symbol node will store that.
2303 if (type.getBasicType() == EbtStruct)
2304 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002305 symbol = new TIntermSymbol(0, "", type);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002306 }
jchen104cdac9e2017-05-08 11:01:20 +08002307 else if (IsAtomicCounter(publicType.getBasicType()))
2308 {
2309 setAtomicCounterBindingDefaultOffset(publicType, identifierOrTypeLocation);
2310 }
Olli Etuahobab4c082015-04-24 16:38:49 +03002311 }
2312 else
Jamie Madill60ed9812013-06-06 11:56:46 -04002313 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002314 nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002315
Olli Etuaho856c4972016-08-08 11:38:39 +03002316 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002317
jchen104cdac9e2017-05-08 11:01:20 +08002318 if (IsAtomicCounter(publicType.getBasicType()))
2319 {
2320
2321 checkAtomicCounterOffsetIsNotOverlapped(publicType, kAtomicCounterSize, false,
2322 identifierOrTypeLocation, type);
2323 }
2324
Olli Etuaho2935c582015-04-08 14:32:06 +03002325 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07002326 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04002327
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002328 if (variable)
Olli Etuaho13389b62016-10-16 11:48:18 +01002329 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002330 symbol = new TIntermSymbol(variable->getUniqueId(), identifier, type);
Olli Etuaho13389b62016-10-16 11:48:18 +01002331 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002332 }
2333
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002334 TIntermDeclaration *declaration = new TIntermDeclaration();
2335 declaration->setLine(identifierOrTypeLocation);
2336 if (symbol)
2337 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002338 symbol->setLine(identifierOrTypeLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002339 declaration->appendDeclarator(symbol);
2340 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002341 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002342}
2343
Olli Etuaho13389b62016-10-16 11:48:18 +01002344TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
2345 const TSourceLoc &identifierLocation,
2346 const TString &identifier,
2347 const TSourceLoc &indexLocation,
2348 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04002349{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002350 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002351
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002352 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2353 identifierLocation);
2354
2355 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002356
Olli Etuaho856c4972016-08-08 11:38:39 +03002357 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002358
Olli Etuaho8a176262016-08-16 14:23:01 +03002359 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002360
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002361 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002362
Olli Etuaho856c4972016-08-08 11:38:39 +03002363 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002364 // Make the type an array even if size check failed.
2365 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
Olli Etuaho96f6adf2017-08-16 11:18:54 +03002366 arrayType.makeArray(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04002367
jchen104cdac9e2017-05-08 11:01:20 +08002368 if (IsAtomicCounter(publicType.getBasicType()))
2369 {
2370 checkAtomicCounterOffsetIsNotOverlapped(publicType, kAtomicCounterArrayStride * size, false,
2371 identifierLocation, arrayType);
2372 }
2373
Olli Etuaho2935c582015-04-08 14:32:06 +03002374 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002375 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04002376
Olli Etuaho13389b62016-10-16 11:48:18 +01002377 TIntermDeclaration *declaration = new TIntermDeclaration();
2378 declaration->setLine(identifierLocation);
2379
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002380 if (variable)
Olli Etuaho13389b62016-10-16 11:48:18 +01002381 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002382 TIntermSymbol *symbol = new TIntermSymbol(variable->getUniqueId(), identifier, arrayType);
2383 symbol->setLine(identifierLocation);
Olli Etuaho13389b62016-10-16 11:48:18 +01002384 declaration->appendDeclarator(symbol);
2385 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002386
Olli Etuaho13389b62016-10-16 11:48:18 +01002387 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002388}
2389
Olli Etuaho13389b62016-10-16 11:48:18 +01002390TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
2391 const TSourceLoc &identifierLocation,
2392 const TString &identifier,
2393 const TSourceLoc &initLocation,
2394 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04002395{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002396 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002397
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002398 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2399 identifierLocation);
2400
2401 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002402
Olli Etuaho13389b62016-10-16 11:48:18 +01002403 TIntermDeclaration *declaration = new TIntermDeclaration();
2404 declaration->setLine(identifierLocation);
2405
2406 TIntermBinary *initNode = nullptr;
Olli Etuaho914b79a2017-06-19 16:03:19 +03002407 if (executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04002408 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002409 if (initNode)
2410 {
2411 declaration->appendDeclarator(initNode);
2412 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002413 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002414 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002415}
2416
Olli Etuaho13389b62016-10-16 11:48:18 +01002417TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
Jamie Madillb98c3a82015-07-23 14:26:04 -04002418 TPublicType &publicType,
2419 const TSourceLoc &identifierLocation,
2420 const TString &identifier,
2421 const TSourceLoc &indexLocation,
2422 TIntermTyped *indexExpression,
2423 const TSourceLoc &initLocation,
2424 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002425{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002426 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002427
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002428 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2429 identifierLocation);
2430
2431 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002432
Olli Etuaho8a176262016-08-16 14:23:01 +03002433 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002434
2435 TPublicType arrayType(publicType);
2436
Olli Etuaho856c4972016-08-08 11:38:39 +03002437 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002438 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2439 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002440 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002441 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002442 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002443 }
2444 // Make the type an array even if size check failed.
2445 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2446 arrayType.setArraySize(size);
2447
Olli Etuaho13389b62016-10-16 11:48:18 +01002448 TIntermDeclaration *declaration = new TIntermDeclaration();
2449 declaration->setLine(identifierLocation);
2450
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002451 // initNode will correspond to the whole of "type b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002452 TIntermBinary *initNode = nullptr;
Olli Etuaho914b79a2017-06-19 16:03:19 +03002453 if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002454 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002455 if (initNode)
2456 {
2457 declaration->appendDeclarator(initNode);
2458 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002459 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002460
2461 return declaration;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002462}
2463
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002464TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
Martin Radev70866b82016-07-22 15:27:42 +03002465 const TTypeQualifierBuilder &typeQualifierBuilder,
2466 const TSourceLoc &identifierLoc,
2467 const TString *identifier,
2468 const TSymbol *symbol)
Jamie Madill47e3ec02014-08-20 16:38:33 -04002469{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002470 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002471
Martin Radev70866b82016-07-22 15:27:42 +03002472 if (!typeQualifier.invariant)
2473 {
2474 error(identifierLoc, "Expected invariant", identifier->c_str());
2475 return nullptr;
2476 }
2477 if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
2478 {
2479 return nullptr;
2480 }
Jamie Madill47e3ec02014-08-20 16:38:33 -04002481 if (!symbol)
2482 {
2483 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002484 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04002485 }
Martin Radev70866b82016-07-22 15:27:42 +03002486 if (!IsQualifierUnspecified(typeQualifier.qualifier))
Jamie Madill47e3ec02014-08-20 16:38:33 -04002487 {
Martin Radev70866b82016-07-22 15:27:42 +03002488 error(identifierLoc, "invariant declaration specifies qualifier",
2489 getQualifierString(typeQualifier.qualifier));
Jamie Madill47e3ec02014-08-20 16:38:33 -04002490 }
Martin Radev70866b82016-07-22 15:27:42 +03002491 if (typeQualifier.precision != EbpUndefined)
2492 {
2493 error(identifierLoc, "invariant declaration specifies precision",
2494 getPrecisionString(typeQualifier.precision));
2495 }
2496 if (!typeQualifier.layoutQualifier.isEmpty())
2497 {
2498 error(identifierLoc, "invariant declaration specifies layout", "'layout'");
2499 }
2500
2501 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
Olli Etuaho0f684632017-07-13 12:42:15 +03002502 if (!variable)
2503 {
2504 return nullptr;
2505 }
Martin Radev70866b82016-07-22 15:27:42 +03002506 const TType &type = variable->getType();
2507
2508 checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
2509 typeQualifier.line);
Olli Etuaho43364892017-02-13 16:00:12 +00002510 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev70866b82016-07-22 15:27:42 +03002511
2512 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
2513
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002514 TIntermSymbol *intermSymbol = new TIntermSymbol(variable->getUniqueId(), *identifier, type);
2515 intermSymbol->setLine(identifierLoc);
Martin Radev70866b82016-07-22 15:27:42 +03002516
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002517 return new TIntermInvariantDeclaration(intermSymbol, identifierLoc);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002518}
2519
Olli Etuaho13389b62016-10-16 11:48:18 +01002520void TParseContext::parseDeclarator(TPublicType &publicType,
2521 const TSourceLoc &identifierLocation,
2522 const TString &identifier,
2523 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002524{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002525 // If the declaration starting this declarator list was empty (example: int,), some checks were
2526 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002527 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002528 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002529 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2530 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002531 }
2532
Olli Etuaho856c4972016-08-08 11:38:39 +03002533 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002534
Olli Etuaho856c4972016-08-08 11:38:39 +03002535 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002536
Olli Etuaho2935c582015-04-08 14:32:06 +03002537 TVariable *variable = nullptr;
Olli Etuaho43364892017-02-13 16:00:12 +00002538 TType type(publicType);
jchen104cdac9e2017-05-08 11:01:20 +08002539 if (IsAtomicCounter(publicType.getBasicType()))
2540 {
2541 checkAtomicCounterOffsetIsNotOverlapped(publicType, kAtomicCounterSize, true,
2542 identifierLocation, type);
2543 }
Olli Etuaho43364892017-02-13 16:00:12 +00002544 declareVariable(identifierLocation, identifier, type, &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002545
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002546 if (variable)
Olli Etuaho13389b62016-10-16 11:48:18 +01002547 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002548 TIntermSymbol *symbol = new TIntermSymbol(variable->getUniqueId(), identifier, type);
2549 symbol->setLine(identifierLocation);
Olli Etuaho13389b62016-10-16 11:48:18 +01002550 declarationOut->appendDeclarator(symbol);
2551 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002552}
2553
Olli Etuaho13389b62016-10-16 11:48:18 +01002554void TParseContext::parseArrayDeclarator(TPublicType &publicType,
2555 const TSourceLoc &identifierLocation,
2556 const TString &identifier,
2557 const TSourceLoc &arrayLocation,
2558 TIntermTyped *indexExpression,
2559 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002560{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002561 // If the declaration starting this declarator list was empty (example: int,), some checks were
2562 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002563 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002564 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002565 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2566 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002567 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002568
Olli Etuaho856c4972016-08-08 11:38:39 +03002569 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002570
Olli Etuaho856c4972016-08-08 11:38:39 +03002571 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002572
Olli Etuaho8a176262016-08-16 14:23:01 +03002573 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04002574 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002575 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03002576 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho96f6adf2017-08-16 11:18:54 +03002577 arrayType.makeArray(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002578
jchen104cdac9e2017-05-08 11:01:20 +08002579 if (IsAtomicCounter(publicType.getBasicType()))
2580 {
2581 checkAtomicCounterOffsetIsNotOverlapped(publicType, kAtomicCounterArrayStride * size,
2582 true, identifierLocation, arrayType);
2583 }
2584
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002585 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002586 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04002587
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002588 if (variable)
Olli Etuahod7ceaa12017-07-12 17:46:35 +03002589 {
2590 TIntermSymbol *symbol =
2591 new TIntermSymbol(variable->getUniqueId(), identifier, arrayType);
2592 symbol->setLine(identifierLocation);
2593 declarationOut->appendDeclarator(symbol);
2594 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002595 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002596}
2597
Olli Etuaho13389b62016-10-16 11:48:18 +01002598void TParseContext::parseInitDeclarator(const TPublicType &publicType,
2599 const TSourceLoc &identifierLocation,
2600 const TString &identifier,
2601 const TSourceLoc &initLocation,
2602 TIntermTyped *initializer,
2603 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002604{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002605 // If the declaration starting this declarator list was empty (example: int,), some checks were
2606 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002607 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002608 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002609 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2610 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002611 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002612
Olli Etuaho856c4972016-08-08 11:38:39 +03002613 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002614
Olli Etuaho13389b62016-10-16 11:48:18 +01002615 TIntermBinary *initNode = nullptr;
Olli Etuaho914b79a2017-06-19 16:03:19 +03002616 if (executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04002617 {
2618 //
2619 // build the intermediate representation
2620 //
Olli Etuaho13389b62016-10-16 11:48:18 +01002621 if (initNode)
Jamie Madill502d66f2013-06-20 11:55:52 -04002622 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002623 declarationOut->appendDeclarator(initNode);
Jamie Madill502d66f2013-06-20 11:55:52 -04002624 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002625 }
2626}
2627
Olli Etuaho13389b62016-10-16 11:48:18 +01002628void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
2629 const TSourceLoc &identifierLocation,
2630 const TString &identifier,
2631 const TSourceLoc &indexLocation,
2632 TIntermTyped *indexExpression,
2633 const TSourceLoc &initLocation,
2634 TIntermTyped *initializer,
2635 TIntermDeclaration *declarationOut)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002636{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002637 // If the declaration starting this declarator list was empty (example: int,), some checks were
2638 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002639 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002640 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002641 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2642 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002643 }
2644
Olli Etuaho856c4972016-08-08 11:38:39 +03002645 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002646
Olli Etuaho8a176262016-08-16 14:23:01 +03002647 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002648
2649 TPublicType arrayType(publicType);
2650
Olli Etuaho856c4972016-08-08 11:38:39 +03002651 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002652 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2653 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002654 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002655 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002656 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002657 }
2658 // Make the type an array even if size check failed.
2659 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2660 arrayType.setArraySize(size);
2661
2662 // initNode will correspond to the whole of "b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002663 TIntermBinary *initNode = nullptr;
Olli Etuaho914b79a2017-06-19 16:03:19 +03002664 if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002665 {
2666 if (initNode)
2667 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002668 declarationOut->appendDeclarator(initNode);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002669 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002670 }
2671}
2672
jchen104cdac9e2017-05-08 11:01:20 +08002673void TParseContext::setAtomicCounterBindingDefaultOffset(const TPublicType &publicType,
2674 const TSourceLoc &location)
2675{
2676 const TLayoutQualifier &layoutQualifier = publicType.layoutQualifier;
2677 checkAtomicCounterBindingIsValid(location, layoutQualifier.binding);
2678 if (layoutQualifier.binding == -1 || layoutQualifier.offset == -1)
2679 {
2680 error(location, "Requires both binding and offset", "layout");
2681 return;
2682 }
2683 mAtomicCounterBindingStates[layoutQualifier.binding].setDefaultOffset(layoutQualifier.offset);
2684}
2685
Olli Etuahocce89652017-06-19 16:04:09 +03002686void TParseContext::parseDefaultPrecisionQualifier(const TPrecision precision,
2687 const TPublicType &type,
2688 const TSourceLoc &loc)
2689{
2690 if ((precision == EbpHigh) && (getShaderType() == GL_FRAGMENT_SHADER) &&
2691 !getFragmentPrecisionHigh())
2692 {
2693 error(loc, "precision is not supported in fragment shader", "highp");
2694 }
2695
2696 if (!CanSetDefaultPrecisionOnType(type))
2697 {
2698 error(loc, "illegal type argument for default precision qualifier",
2699 getBasicString(type.getBasicType()));
2700 return;
2701 }
2702 symbolTable.setDefaultPrecision(type.getBasicType(), precision);
2703}
2704
Shaob5cc1192017-07-06 10:47:20 +08002705bool TParseContext::checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier)
2706{
2707 switch (typeQualifier.layoutQualifier.primitiveType)
2708 {
2709 case EptLines:
2710 case EptLinesAdjacency:
2711 case EptTriangles:
2712 case EptTrianglesAdjacency:
2713 return typeQualifier.qualifier == EvqGeometryIn;
2714
2715 case EptLineStrip:
2716 case EptTriangleStrip:
2717 return typeQualifier.qualifier == EvqGeometryOut;
2718
2719 case EptPoints:
2720 return true;
2721
2722 default:
2723 UNREACHABLE();
2724 return false;
2725 }
2726}
2727
Jiawei Shaod8105a02017-08-08 09:54:36 +08002728void TParseContext::setGeometryShaderInputArraySizes()
2729{
2730 // TODO(jiawei.shao@intel.com): check former input array sizes match the input primitive
2731 // declaration.
2732 ASSERT(mGeometryShaderInputArraySize == 0);
2733 mGeometryShaderInputArraySize =
2734 GetGeometryShaderInputArraySize(mGeometryShaderInputPrimitiveType);
2735}
2736
Shaob5cc1192017-07-06 10:47:20 +08002737bool TParseContext::parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier)
2738{
2739 ASSERT(typeQualifier.qualifier == EvqGeometryIn);
2740
2741 const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
2742
2743 if (layoutQualifier.maxVertices != -1)
2744 {
2745 error(typeQualifier.line,
2746 "max_vertices can only be declared in 'out' layout in a geometry shader", "layout");
2747 return false;
2748 }
2749
2750 // Set mGeometryInputPrimitiveType if exists
2751 if (layoutQualifier.primitiveType != EptUndefined)
2752 {
2753 if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier))
2754 {
2755 error(typeQualifier.line, "invalid primitive type for 'in' layout", "layout");
2756 return false;
2757 }
2758
2759 if (mGeometryShaderInputPrimitiveType == EptUndefined)
2760 {
2761 mGeometryShaderInputPrimitiveType = layoutQualifier.primitiveType;
Jiawei Shaod8105a02017-08-08 09:54:36 +08002762 setGeometryShaderInputArraySizes();
Shaob5cc1192017-07-06 10:47:20 +08002763 }
2764 else if (mGeometryShaderInputPrimitiveType != layoutQualifier.primitiveType)
2765 {
2766 error(typeQualifier.line, "primitive doesn't match earlier input primitive declaration",
2767 "layout");
2768 return false;
2769 }
2770 }
2771
2772 // Set mGeometryInvocations if exists
2773 if (layoutQualifier.invocations > 0)
2774 {
2775 if (mGeometryShaderInvocations == 0)
2776 {
2777 mGeometryShaderInvocations = layoutQualifier.invocations;
2778 }
2779 else if (mGeometryShaderInvocations != layoutQualifier.invocations)
2780 {
2781 error(typeQualifier.line, "invocations contradicts to the earlier declaration",
2782 "layout");
2783 return false;
2784 }
2785 }
2786
2787 return true;
2788}
2789
2790bool TParseContext::parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier)
2791{
2792 ASSERT(typeQualifier.qualifier == EvqGeometryOut);
2793
2794 const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
2795
2796 if (layoutQualifier.invocations > 0)
2797 {
2798 error(typeQualifier.line,
2799 "invocations can only be declared in 'in' layout in a geometry shader", "layout");
2800 return false;
2801 }
2802
2803 // Set mGeometryOutputPrimitiveType if exists
2804 if (layoutQualifier.primitiveType != EptUndefined)
2805 {
2806 if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier))
2807 {
2808 error(typeQualifier.line, "invalid primitive type for 'out' layout", "layout");
2809 return false;
2810 }
2811
2812 if (mGeometryShaderOutputPrimitiveType == EptUndefined)
2813 {
2814 mGeometryShaderOutputPrimitiveType = layoutQualifier.primitiveType;
2815 }
2816 else if (mGeometryShaderOutputPrimitiveType != layoutQualifier.primitiveType)
2817 {
2818 error(typeQualifier.line,
2819 "primitive doesn't match earlier output primitive declaration", "layout");
2820 return false;
2821 }
2822 }
2823
2824 // Set mGeometryMaxVertices if exists
2825 if (layoutQualifier.maxVertices > -1)
2826 {
2827 if (mGeometryShaderMaxVertices == -1)
2828 {
2829 mGeometryShaderMaxVertices = layoutQualifier.maxVertices;
2830 }
2831 else if (mGeometryShaderMaxVertices != layoutQualifier.maxVertices)
2832 {
2833 error(typeQualifier.line, "max_vertices contradicts to the earlier declaration",
2834 "layout");
2835 return false;
2836 }
2837 }
2838
2839 return true;
2840}
2841
Martin Radev70866b82016-07-22 15:27:42 +03002842void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
Jamie Madilla295edf2013-06-06 11:56:48 -04002843{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002844 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madilla295edf2013-06-06 11:56:48 -04002845 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04002846
Martin Radev70866b82016-07-22 15:27:42 +03002847 checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
2848 typeQualifier.line);
2849
Jamie Madillc2128ff2016-07-04 10:26:17 -04002850 // It should never be the case, but some strange parser errors can send us here.
2851 if (layoutQualifier.isEmpty())
2852 {
2853 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04002854 return;
2855 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002856
Martin Radev802abe02016-08-04 17:48:32 +03002857 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04002858 {
Olli Etuaho43364892017-02-13 16:00:12 +00002859 error(typeQualifier.line, "invalid layout qualifier combination", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04002860 return;
2861 }
2862
Olli Etuaho43364892017-02-13 16:00:12 +00002863 checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);
2864
2865 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev2cc85b32016-08-05 16:22:53 +03002866
2867 checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
2868
Andrei Volykhina5527072017-03-22 16:46:30 +03002869 checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv);
2870
jchen104cdac9e2017-05-08 11:01:20 +08002871 checkOffsetIsNotSpecified(typeQualifier.line, layoutQualifier.offset);
2872
Martin Radev802abe02016-08-04 17:48:32 +03002873 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04002874 {
Martin Radev802abe02016-08-04 17:48:32 +03002875 if (mComputeShaderLocalSizeDeclared &&
2876 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
2877 {
2878 error(typeQualifier.line, "Work group size does not match the previous declaration",
2879 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002880 return;
2881 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002882
Martin Radev802abe02016-08-04 17:48:32 +03002883 if (mShaderVersion < 310)
2884 {
2885 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002886 return;
2887 }
Jamie Madill099c0f32013-06-20 11:55:52 -04002888
Martin Radev4c4c8e72016-08-04 12:25:34 +03002889 if (!layoutQualifier.localSize.isAnyValueSet())
Martin Radev802abe02016-08-04 17:48:32 +03002890 {
2891 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002892 return;
2893 }
2894
2895 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
2896 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
2897
2898 const TConstantUnion *maxComputeWorkGroupSizeData =
2899 maxComputeWorkGroupSize->getConstPointer();
2900
2901 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
2902 {
2903 if (layoutQualifier.localSize[i] != -1)
2904 {
2905 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
2906 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
2907 if (mComputeShaderLocalSize[i] < 1 ||
2908 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
2909 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002910 std::stringstream reasonStream;
2911 reasonStream << "invalid value: Value must be at least 1 and no greater than "
2912 << maxComputeWorkGroupSizeValue;
2913 const std::string &reason = reasonStream.str();
Martin Radev802abe02016-08-04 17:48:32 +03002914
Olli Etuaho4de340a2016-12-16 09:32:03 +00002915 error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03002916 return;
2917 }
2918 }
2919 }
2920
2921 mComputeShaderLocalSizeDeclared = true;
2922 }
Shaob5cc1192017-07-06 10:47:20 +08002923 else if (typeQualifier.qualifier == EvqGeometryIn)
2924 {
2925 if (mShaderVersion < 310)
2926 {
2927 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
2928 return;
2929 }
2930
2931 if (!parseGeometryShaderInputLayoutQualifier(typeQualifier))
2932 {
2933 return;
2934 }
2935 }
2936 else if (typeQualifier.qualifier == EvqGeometryOut)
2937 {
2938 if (mShaderVersion < 310)
2939 {
2940 error(typeQualifier.line, "out type qualifier supported in GLSL ES 3.10 only",
2941 "layout");
2942 return;
2943 }
2944
2945 if (!parseGeometryShaderOutputLayoutQualifier(typeQualifier))
2946 {
2947 return;
2948 }
2949 }
Olli Etuaho95468d12017-05-04 11:14:34 +03002950 else if (isMultiviewExtensionEnabled() && typeQualifier.qualifier == EvqVertexIn)
Olli Etuaho09b04a22016-12-15 13:30:26 +00002951 {
2952 // This error is only specified in WebGL, but tightens unspecified behavior in the native
2953 // specification.
2954 if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
2955 {
2956 error(typeQualifier.line, "Number of views does not match the previous declaration",
2957 "layout");
2958 return;
2959 }
2960
2961 if (layoutQualifier.numViews == -1)
2962 {
2963 error(typeQualifier.line, "No num_views specified", "layout");
2964 return;
2965 }
2966
2967 if (layoutQualifier.numViews > mMaxNumViews)
2968 {
2969 error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
2970 "layout");
2971 return;
2972 }
2973
2974 mNumViews = layoutQualifier.numViews;
2975 }
Martin Radev802abe02016-08-04 17:48:32 +03002976 else
Jamie Madill1566ef72013-06-20 11:55:54 -04002977 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00002978 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03002979 {
Martin Radev802abe02016-08-04 17:48:32 +03002980 return;
2981 }
2982
Jiajia Qinbc585152017-06-23 15:42:17 +08002983 if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer)
Martin Radev802abe02016-08-04 17:48:32 +03002984 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002985 error(typeQualifier.line, "invalid qualifier: global layout can only be set for blocks",
Olli Etuaho4de340a2016-12-16 09:32:03 +00002986 getQualifierString(typeQualifier.qualifier));
Martin Radev802abe02016-08-04 17:48:32 +03002987 return;
2988 }
2989
2990 if (mShaderVersion < 300)
2991 {
2992 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
2993 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002994 return;
2995 }
2996
Olli Etuaho09b04a22016-12-15 13:30:26 +00002997 checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002998
2999 if (layoutQualifier.matrixPacking != EmpUnspecified)
3000 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003001 if (typeQualifier.qualifier == EvqUniform)
3002 {
3003 mDefaultUniformMatrixPacking = layoutQualifier.matrixPacking;
3004 }
3005 else if (typeQualifier.qualifier == EvqBuffer)
3006 {
3007 mDefaultBufferMatrixPacking = layoutQualifier.matrixPacking;
3008 }
Martin Radev802abe02016-08-04 17:48:32 +03003009 }
3010
3011 if (layoutQualifier.blockStorage != EbsUnspecified)
3012 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003013 if (typeQualifier.qualifier == EvqUniform)
3014 {
3015 mDefaultUniformBlockStorage = layoutQualifier.blockStorage;
3016 }
3017 else if (typeQualifier.qualifier == EvqBuffer)
3018 {
3019 mDefaultBufferBlockStorage = layoutQualifier.blockStorage;
3020 }
Martin Radev802abe02016-08-04 17:48:32 +03003021 }
Jamie Madill1566ef72013-06-20 11:55:54 -04003022 }
Jamie Madilla295edf2013-06-06 11:56:48 -04003023}
3024
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003025TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
3026 const TFunction &function,
3027 const TSourceLoc &location,
3028 bool insertParametersToSymbolTable)
3029{
Olli Etuahod7cd4ae2017-07-06 15:52:49 +03003030 checkIsNotReserved(location, function.getName());
3031
Olli Etuahofe486322017-03-21 09:30:54 +00003032 TIntermFunctionPrototype *prototype =
3033 new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function));
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003034 // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
3035 // point to the data that already exists in the symbol table.
3036 prototype->getFunctionSymbolInfo()->setFromFunction(function);
3037 prototype->setLine(location);
3038
3039 for (size_t i = 0; i < function.getParamCount(); i++)
3040 {
3041 const TConstParameter &param = function.getParam(i);
3042
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003043 TIntermSymbol *symbol = nullptr;
3044
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003045 // If the parameter has no name, it's not an error, just don't add it to symbol table (could
3046 // be used for unused args).
3047 if (param.name != nullptr)
3048 {
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003049 // Insert the parameter in the symbol table.
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003050 if (insertParametersToSymbolTable)
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003051 {
Olli Etuaho0f684632017-07-13 12:42:15 +03003052 TVariable *variable = symbolTable.declareVariable(param.name, *param.type);
3053 if (variable)
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003054 {
3055 symbol = new TIntermSymbol(variable->getUniqueId(), variable->getName(),
3056 variable->getType());
3057 }
3058 else
3059 {
Olli Etuaho85d624a2017-08-07 13:42:33 +03003060 error(location, "redefinition", param.name->c_str());
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003061 }
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003062 }
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003063 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003064 if (!symbol)
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003065 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003066 // The parameter had no name or declaring the symbol failed - either way, add a nameless
3067 // symbol.
3068 symbol = new TIntermSymbol(0, "", *param.type);
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003069 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003070 symbol->setLine(location);
3071 prototype->appendParameter(symbol);
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003072 }
3073 return prototype;
3074}
3075
Olli Etuaho16c745a2017-01-16 17:02:27 +00003076TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
3077 const TFunction &parsedFunction,
3078 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003079{
Olli Etuaho476197f2016-10-11 13:59:08 +01003080 // Note: function found from the symbol table could be the same as parsedFunction if this is the
3081 // first declaration. Either way the instance in the symbol table is used to track whether the
3082 // function is declared multiple times.
3083 TFunction *function = static_cast<TFunction *>(
3084 symbolTable.find(parsedFunction.getMangledName(), getShaderVersion()));
3085 if (function->hasPrototypeDeclaration() && mShaderVersion == 100)
Olli Etuaho5d653182016-01-04 14:43:28 +02003086 {
3087 // ESSL 1.00.17 section 4.2.7.
3088 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
3089 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02003090 }
Olli Etuaho476197f2016-10-11 13:59:08 +01003091 function->setHasPrototypeDeclaration();
Olli Etuaho5d653182016-01-04 14:43:28 +02003092
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003093 TIntermFunctionPrototype *prototype =
3094 createPrototypeNodeFromFunction(*function, location, false);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003095
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003096 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02003097
3098 if (!symbolTable.atGlobalLevel())
3099 {
3100 // ESSL 3.00.4 section 4.2.4.
3101 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02003102 }
3103
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003104 return prototype;
3105}
3106
Olli Etuaho336b1472016-10-05 16:37:55 +01003107TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003108 TIntermFunctionPrototype *functionPrototype,
Olli Etuaho336b1472016-10-05 16:37:55 +01003109 TIntermBlock *functionBody,
3110 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003111{
Olli Etuahof51fdd22016-10-03 10:03:40 +01003112 // Check that non-void functions have at least one return statement.
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003113 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
3114 {
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003115 error(location, "function does not return a value:",
3116 functionPrototype->getFunctionSymbolInfo()->getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003117 }
3118
Olli Etuahof51fdd22016-10-03 10:03:40 +01003119 if (functionBody == nullptr)
3120 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01003121 functionBody = new TIntermBlock();
Olli Etuahof51fdd22016-10-03 10:03:40 +01003122 functionBody->setLine(location);
3123 }
Olli Etuaho336b1472016-10-05 16:37:55 +01003124 TIntermFunctionDefinition *functionNode =
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003125 new TIntermFunctionDefinition(functionPrototype, functionBody);
Olli Etuaho336b1472016-10-05 16:37:55 +01003126 functionNode->setLine(location);
Olli Etuahof51fdd22016-10-03 10:03:40 +01003127
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003128 symbolTable.pop();
Olli Etuahof51fdd22016-10-03 10:03:40 +01003129 return functionNode;
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003130}
3131
Olli Etuaho476197f2016-10-11 13:59:08 +01003132void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
3133 TFunction **function,
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003134 TIntermFunctionPrototype **prototypeOut)
Jamie Madill185fb402015-06-12 15:48:48 -04003135{
Olli Etuaho476197f2016-10-11 13:59:08 +01003136 ASSERT(function);
3137 ASSERT(*function);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003138 const TSymbol *builtIn =
Olli Etuaho476197f2016-10-11 13:59:08 +01003139 symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04003140
3141 if (builtIn)
3142 {
Olli Etuaho476197f2016-10-11 13:59:08 +01003143 error(location, "built-in functions cannot be redefined", (*function)->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04003144 }
Olli Etuaho476197f2016-10-11 13:59:08 +01003145 else
Jamie Madill185fb402015-06-12 15:48:48 -04003146 {
Olli Etuaho476197f2016-10-11 13:59:08 +01003147 TFunction *prevDec = static_cast<TFunction *>(
3148 symbolTable.find((*function)->getMangledName(), getShaderVersion()));
3149
3150 // Note: 'prevDec' could be 'function' if this is the first time we've seen function as it
3151 // would have just been put in the symbol table. Otherwise, we're looking up an earlier
3152 // occurance.
3153 if (*function != prevDec)
3154 {
3155 // Swap the parameters of the previous declaration to the parameters of the function
3156 // definition (parameter names may differ).
3157 prevDec->swapParameters(**function);
3158
3159 // The function definition will share the same symbol as any previous declaration.
3160 *function = prevDec;
3161 }
3162
3163 if ((*function)->isDefined())
3164 {
3165 error(location, "function already has a body", (*function)->getName().c_str());
3166 }
3167
3168 (*function)->setDefined();
Jamie Madill185fb402015-06-12 15:48:48 -04003169 }
Jamie Madill185fb402015-06-12 15:48:48 -04003170
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003171 // Remember the return type for later checking for return statements.
Olli Etuaho476197f2016-10-11 13:59:08 +01003172 mCurrentFunctionType = &((*function)->getReturnType());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003173 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04003174
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003175 *prototypeOut = createPrototypeNodeFromFunction(**function, location, true);
Jamie Madill185fb402015-06-12 15:48:48 -04003176 setLoopNestingLevel(0);
3177}
3178
Jamie Madillb98c3a82015-07-23 14:26:04 -04003179TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04003180{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00003181 //
Olli Etuaho5d653182016-01-04 14:43:28 +02003182 // We don't know at this point whether this is a function definition or a prototype.
3183 // The definition production code will check for redefinitions.
3184 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00003185 //
Olli Etuaho5d653182016-01-04 14:43:28 +02003186 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
3187 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00003188 //
3189 TFunction *prevDec =
3190 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05303191
Martin Radevda6254b2016-12-14 17:00:36 +02003192 if (getShaderVersion() >= 300 &&
3193 symbolTable.hasUnmangledBuiltInForShaderVersion(function->getName().c_str(),
3194 getShaderVersion()))
Olli Etuahoc4a96d62015-07-23 17:37:39 +05303195 {
Martin Radevda6254b2016-12-14 17:00:36 +02003196 // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions.
Olli Etuahoc4a96d62015-07-23 17:37:39 +05303197 // Therefore overloading or redefining builtin functions is an error.
3198 error(location, "Name of a built-in function cannot be redeclared as function",
3199 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05303200 }
3201 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04003202 {
3203 if (prevDec->getReturnType() != function->getReturnType())
3204 {
Olli Etuaho476197f2016-10-11 13:59:08 +01003205 error(location, "function must have the same return type in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04003206 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04003207 }
3208 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
3209 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003210 if (prevDec->getParam(i).type->getQualifier() !=
3211 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04003212 {
Olli Etuaho476197f2016-10-11 13:59:08 +01003213 error(location,
3214 "function must have the same parameter qualifiers in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04003215 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04003216 }
3217 }
3218 }
3219
3220 //
3221 // Check for previously declared variables using the same name.
3222 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00003223 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04003224 if (prevSym)
3225 {
3226 if (!prevSym->isFunction())
3227 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003228 error(location, "redefinition of a function", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04003229 }
3230 }
3231 else
3232 {
3233 // Insert the unmangled name to detect potential future redefinition as a variable.
Olli Etuaho476197f2016-10-11 13:59:08 +01003234 symbolTable.getOuterLevel()->insertUnmangled(function);
Jamie Madill185fb402015-06-12 15:48:48 -04003235 }
3236
3237 // We're at the inner scope level of the function's arguments and body statement.
3238 // Add the function prototype to the surrounding scope instead.
3239 symbolTable.getOuterLevel()->insert(function);
3240
Olli Etuaho78d13742017-01-18 13:06:10 +00003241 // Raise error message if main function takes any parameters or return anything other than void
3242 if (function->getName() == "main")
3243 {
3244 if (function->getParamCount() > 0)
3245 {
3246 error(location, "function cannot take any parameter(s)", "main");
3247 }
3248 if (function->getReturnType().getBasicType() != EbtVoid)
3249 {
3250 error(location, "main function cannot return a value",
3251 function->getReturnType().getBasicString());
3252 }
3253 }
3254
Jamie Madill185fb402015-06-12 15:48:48 -04003255 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04003256 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
3257 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04003258 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
3259 //
3260 return function;
3261}
3262
Olli Etuaho9de84a52016-06-14 17:36:01 +03003263TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
3264 const TString *name,
3265 const TSourceLoc &location)
3266{
3267 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
3268 {
3269 error(location, "no qualifiers allowed for function return",
3270 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03003271 }
3272 if (!type.layoutQualifier.isEmpty())
3273 {
3274 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03003275 }
jchen10cc2a10e2017-05-03 14:05:12 +08003276 // make sure an opaque type is not involved as well...
3277 std::string reason(getBasicString(type.getBasicType()));
3278 reason += "s can't be function return values";
3279 checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03003280 if (mShaderVersion < 300)
3281 {
3282 // Array return values are forbidden, but there's also no valid syntax for declaring array
3283 // return values in ESSL 1.00.
Olli Etuaho77ba4082016-12-16 12:01:18 +00003284 ASSERT(type.arraySize == 0 || mDiagnostics->numErrors() > 0);
Olli Etuahoe29324f2016-06-15 10:58:03 +03003285
3286 if (type.isStructureContainingArrays())
3287 {
3288 // ESSL 1.00.17 section 6.1 Function Definitions
3289 error(location, "structures containing arrays can't be function return values",
3290 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03003291 }
3292 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03003293
3294 // Add the function as a prototype after parsing it (we do not support recursion)
Olli Etuahoa5e693a2017-07-13 16:07:26 +03003295 return new TFunction(&symbolTable, name, new TType(type));
Olli Etuaho9de84a52016-06-14 17:36:01 +03003296}
3297
Olli Etuahocce89652017-06-19 16:04:09 +03003298TFunction *TParseContext::addNonConstructorFunc(const TString *name, const TSourceLoc &loc)
3299{
Olli Etuahocce89652017-06-19 16:04:09 +03003300 const TType *returnType = TCache::getType(EbtVoid, EbpUndefined);
Olli Etuahoa5e693a2017-07-13 16:07:26 +03003301 return new TFunction(&symbolTable, name, returnType);
Olli Etuahocce89652017-06-19 16:04:09 +03003302}
3303
Olli Etuahoa7ecec32017-05-08 17:43:55 +03003304TFunction *TParseContext::addConstructorFunc(const TPublicType &publicType)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00003305{
Olli Etuahocce89652017-06-19 16:04:09 +03003306 if (mShaderVersion < 300 && publicType.array)
3307 {
3308 error(publicType.getLine(), "array constructor supported in GLSL ES 3.00 and above only",
3309 "[]");
3310 }
Martin Radev4a9cd802016-09-01 16:51:51 +03003311 if (publicType.isStructSpecifier())
Olli Etuahobd163f62015-11-13 12:15:38 +02003312 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003313 error(publicType.getLine(), "constructor can't be a structure definition",
3314 getBasicString(publicType.getBasicType()));
Olli Etuahobd163f62015-11-13 12:15:38 +02003315 }
3316
Olli Etuahoa7ecec32017-05-08 17:43:55 +03003317 TType *type = new TType(publicType);
3318 if (!type->canBeConstructed())
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00003319 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03003320 error(publicType.getLine(), "cannot construct this type",
3321 getBasicString(publicType.getBasicType()));
3322 type->setBasicType(EbtFloat);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00003323 }
3324
Olli Etuahoa5e693a2017-07-13 16:07:26 +03003325 return new TFunction(&symbolTable, nullptr, type, EOpConstruct);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00003326}
3327
Olli Etuahocce89652017-06-19 16:04:09 +03003328TParameter TParseContext::parseParameterDeclarator(const TPublicType &publicType,
3329 const TString *name,
3330 const TSourceLoc &nameLoc)
3331{
3332 if (publicType.getBasicType() == EbtVoid)
3333 {
3334 error(nameLoc, "illegal use of type 'void'", name->c_str());
3335 }
3336 checkIsNotReserved(nameLoc, *name);
3337 TType *type = new TType(publicType);
3338 TParameter param = {name, type};
3339 return param;
3340}
3341
3342TParameter TParseContext::parseParameterArrayDeclarator(const TString *identifier,
3343 const TSourceLoc &identifierLoc,
3344 TIntermTyped *arraySize,
3345 const TSourceLoc &arrayLoc,
3346 TPublicType *type)
3347{
3348 checkIsValidTypeForArray(arrayLoc, *type);
3349 unsigned int size = checkIsValidArraySize(arrayLoc, arraySize);
3350 type->setArraySize(size);
3351 return parseParameterDeclarator(*type, identifier, identifierLoc);
3352}
3353
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003354bool TParseContext::checkUnsizedArrayConstructorArgumentDimensionality(TIntermSequence *arguments,
3355 TType type,
3356 const TSourceLoc &line)
3357{
3358 if (arguments->empty())
3359 {
3360 error(line, "implicitly sized array constructor must have at least one argument", "[]");
3361 return false;
3362 }
3363 for (TIntermNode *arg : *arguments)
3364 {
3365 TIntermTyped *element = arg->getAsTyped();
3366 ASSERT(element);
3367 size_t dimensionalityFromElement = element->getType().getArraySizes().size() + 1u;
3368 if (dimensionalityFromElement > type.getArraySizes().size())
3369 {
3370 error(line, "constructing from a non-dereferenced array", "constructor");
3371 return false;
3372 }
3373 else if (dimensionalityFromElement < type.getArraySizes().size())
3374 {
3375 if (dimensionalityFromElement == 1u)
3376 {
3377 error(line, "implicitly sized array of arrays constructor argument is not an array",
3378 "constructor");
3379 }
3380 else
3381 {
3382 error(line,
3383 "implicitly sized array of arrays constructor argument dimensionality is too "
3384 "low",
3385 "constructor");
3386 }
3387 return false;
3388 }
3389 }
3390 return true;
3391}
3392
Jamie Madillb98c3a82015-07-23 14:26:04 -04003393// This function is used to test for the correctness of the parameters passed to various constructor
3394// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003395//
Olli Etuaho856c4972016-08-08 11:38:39 +03003396// 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 +00003397//
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08003398TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00003399 TType type,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303400 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003401{
Olli Etuaho856c4972016-08-08 11:38:39 +03003402 if (type.isUnsizedArray())
3403 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003404 if (!checkUnsizedArrayConstructorArgumentDimensionality(arguments, type, line))
Olli Etuahobbe9fb52016-11-03 17:16:05 +00003405 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003406 type.sizeUnsizedArrays(TVector<unsigned int>());
Olli Etuaho3ec75682017-07-05 17:02:55 +03003407 return CreateZeroNode(type);
Olli Etuahobbe9fb52016-11-03 17:16:05 +00003408 }
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003409 TIntermTyped *firstElement = arguments->at(0)->getAsTyped();
3410 ASSERT(firstElement);
3411 type.setArraySize(type.getArraySizes().size() - 1u,
3412 static_cast<unsigned int>(arguments->size()));
3413 for (size_t i = 0; i < firstElement->getType().getArraySizes().size(); ++i)
3414 {
3415 if (type.getArraySizes()[i] == 0u)
3416 {
3417 type.setArraySize(i, firstElement->getType().getArraySizes().at(i));
3418 }
3419 }
3420 ASSERT(!type.isUnsizedArray());
Olli Etuaho856c4972016-08-08 11:38:39 +03003421 }
Olli Etuaho856c4972016-08-08 11:38:39 +03003422
Olli Etuahoa7ecec32017-05-08 17:43:55 +03003423 if (!checkConstructorArguments(line, arguments, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03003424 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03003425 return CreateZeroNode(type);
Olli Etuaho856c4972016-08-08 11:38:39 +03003426 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003427
Olli Etuahoa7ecec32017-05-08 17:43:55 +03003428 TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08003429 constructorNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003430
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003431 // TODO(oetuaho@nvidia.com): Add support for folding array constructors.
3432 if (!constructorNode->isArray())
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003433 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003434 return constructorNode->fold(mDiagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003435 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08003436 return constructorNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003437}
3438
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003439//
3440// Interface/uniform blocks
Jiawei Shaod8105a02017-08-08 09:54:36 +08003441// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003442//
Olli Etuaho13389b62016-10-16 11:48:18 +01003443TIntermDeclaration *TParseContext::addInterfaceBlock(
Martin Radev70866b82016-07-22 15:27:42 +03003444 const TTypeQualifierBuilder &typeQualifierBuilder,
3445 const TSourceLoc &nameLine,
3446 const TString &blockName,
3447 TFieldList *fieldList,
3448 const TString *instanceName,
3449 const TSourceLoc &instanceLine,
3450 TIntermTyped *arrayIndex,
3451 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003452{
Olli Etuaho856c4972016-08-08 11:38:39 +03003453 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003454
Olli Etuaho77ba4082016-12-16 12:01:18 +00003455 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03003456
Jiajia Qinbc585152017-06-23 15:42:17 +08003457 if (mShaderVersion < 310 && typeQualifier.qualifier != EvqUniform)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003458 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003459 error(typeQualifier.line,
3460 "invalid qualifier: interface blocks must be uniform in version lower than GLSL ES "
3461 "3.10",
3462 getQualifierString(typeQualifier.qualifier));
3463 }
3464 else if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer)
3465 {
3466 error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform or buffer",
Olli Etuaho4de340a2016-12-16 09:32:03 +00003467 getQualifierString(typeQualifier.qualifier));
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003468 }
3469
Martin Radev70866b82016-07-22 15:27:42 +03003470 if (typeQualifier.invariant)
3471 {
3472 error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
3473 }
3474
Jiajia Qinbc585152017-06-23 15:42:17 +08003475 if (typeQualifier.qualifier != EvqBuffer)
3476 {
3477 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
3478 }
Olli Etuaho43364892017-02-13 16:00:12 +00003479
jchen10af713a22017-04-19 09:10:56 +08003480 // add array index
3481 unsigned int arraySize = 0;
3482 if (arrayIndex != nullptr)
3483 {
3484 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
3485 }
3486
3487 if (mShaderVersion < 310)
3488 {
3489 checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
3490 }
3491 else
3492 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003493 checkBlockBindingIsValid(typeQualifier.line, typeQualifier.qualifier,
3494 typeQualifier.layoutQualifier.binding, arraySize);
jchen10af713a22017-04-19 09:10:56 +08003495 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003496
Andrei Volykhina5527072017-03-22 16:46:30 +03003497 checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
3498
Jamie Madill099c0f32013-06-20 11:55:52 -04003499 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03003500 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003501
Jamie Madill099c0f32013-06-20 11:55:52 -04003502 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
3503 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003504 if (typeQualifier.qualifier == EvqUniform)
3505 {
3506 blockLayoutQualifier.matrixPacking = mDefaultUniformMatrixPacking;
3507 }
3508 else if (typeQualifier.qualifier == EvqBuffer)
3509 {
3510 blockLayoutQualifier.matrixPacking = mDefaultBufferMatrixPacking;
3511 }
Jamie Madill099c0f32013-06-20 11:55:52 -04003512 }
3513
Jamie Madill1566ef72013-06-20 11:55:54 -04003514 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
3515 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003516 if (typeQualifier.qualifier == EvqUniform)
3517 {
3518 blockLayoutQualifier.blockStorage = mDefaultUniformBlockStorage;
3519 }
3520 else if (typeQualifier.qualifier == EvqBuffer)
3521 {
3522 blockLayoutQualifier.blockStorage = mDefaultBufferBlockStorage;
3523 }
Jamie Madill1566ef72013-06-20 11:55:54 -04003524 }
3525
Olli Etuaho856c4972016-08-08 11:38:39 +03003526 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003527
Martin Radev2cc85b32016-08-05 16:22:53 +03003528 checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
3529
Olli Etuaho0f684632017-07-13 12:42:15 +03003530 if (!symbolTable.declareInterfaceBlockName(&blockName))
Arun Patole7e7e68d2015-05-22 12:02:25 +05303531 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003532 error(nameLine, "redefinition of an interface block name", blockName.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003533 }
3534
Jamie Madill98493dd2013-07-08 14:39:03 -04003535 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05303536 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
3537 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003538 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05303539 TType *fieldType = field->type();
jchen10cc2a10e2017-05-03 14:05:12 +08003540 if (IsOpaqueType(fieldType->getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +05303541 {
jchen10cc2a10e2017-05-03 14:05:12 +08003542 std::string reason("unsupported type - ");
3543 reason += fieldType->getBasicString();
3544 reason += " types are not allowed in interface blocks";
3545 error(field->line(), reason.c_str(), fieldType->getBasicString());
Martin Radev2cc85b32016-08-05 16:22:53 +03003546 }
3547
Jamie Madill98493dd2013-07-08 14:39:03 -04003548 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003549 switch (qualifier)
3550 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003551 case EvqGlobal:
Jiajia Qinbc585152017-06-23 15:42:17 +08003552 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003553 case EvqUniform:
Jiajia Qinbc585152017-06-23 15:42:17 +08003554 if (typeQualifier.qualifier == EvqBuffer)
3555 {
3556 error(field->line(), "invalid qualifier on shader storage block member",
3557 getQualifierString(qualifier));
3558 }
3559 break;
3560 case EvqBuffer:
3561 if (typeQualifier.qualifier == EvqUniform)
3562 {
3563 error(field->line(), "invalid qualifier on uniform block member",
3564 getQualifierString(qualifier));
3565 }
Jamie Madillb98c3a82015-07-23 14:26:04 -04003566 break;
3567 default:
3568 error(field->line(), "invalid qualifier on interface block member",
3569 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003570 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003571 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003572
Martin Radev70866b82016-07-22 15:27:42 +03003573 if (fieldType->isInvariant())
3574 {
3575 error(field->line(), "invalid qualifier on interface block member", "invariant");
3576 }
3577
Jamie Madilla5efff92013-06-06 11:56:47 -04003578 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04003579 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03003580 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
jchen10af713a22017-04-19 09:10:56 +08003581 checkBindingIsNotSpecified(field->line(), fieldLayoutQualifier.binding);
Jamie Madill099c0f32013-06-20 11:55:52 -04003582
Jamie Madill98493dd2013-07-08 14:39:03 -04003583 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04003584 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003585 error(field->line(), "invalid layout qualifier: cannot be used here",
3586 getBlockStorageString(fieldLayoutQualifier.blockStorage));
Jamie Madill1566ef72013-06-20 11:55:54 -04003587 }
3588
Jamie Madill98493dd2013-07-08 14:39:03 -04003589 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04003590 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003591 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04003592 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03003593 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04003594 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003595 warning(field->line(),
3596 "extraneous layout qualifier: only has an effect on matrix types",
3597 getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
Jamie Madill099c0f32013-06-20 11:55:52 -04003598 }
3599
Jamie Madill98493dd2013-07-08 14:39:03 -04003600 fieldType->setLayoutQualifier(fieldLayoutQualifier);
Jiajia Qinbc585152017-06-23 15:42:17 +08003601
3602 if (typeQualifier.qualifier == EvqBuffer)
3603 {
3604 // set memory qualifiers
3605 // GLSL ES 3.10 session 4.9 [Memory Access Qualifiers]. When a block declaration is
3606 // qualified with a memory qualifier, it is as if all of its members were declared with
3607 // the same memory qualifier.
3608 const TMemoryQualifier &blockMemoryQualifier = typeQualifier.memoryQualifier;
3609 TMemoryQualifier fieldMemoryQualifier = fieldType->getMemoryQualifier();
3610 fieldMemoryQualifier.readonly |= blockMemoryQualifier.readonly;
3611 fieldMemoryQualifier.writeonly |= blockMemoryQualifier.writeonly;
3612 fieldMemoryQualifier.coherent |= blockMemoryQualifier.coherent;
3613 fieldMemoryQualifier.restrictQualifier |= blockMemoryQualifier.restrictQualifier;
3614 fieldMemoryQualifier.volatileQualifier |= blockMemoryQualifier.volatileQualifier;
3615 // TODO(jiajia.qin@intel.com): Decide whether if readonly and writeonly buffer variable
3616 // is legal. See bug https://github.com/KhronosGroup/OpenGL-API/issues/7
3617 fieldType->setMemoryQualifier(fieldMemoryQualifier);
3618 }
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003619 }
3620
Jamie Madillb98c3a82015-07-23 14:26:04 -04003621 TInterfaceBlock *interfaceBlock =
Shaob18c33e2017-08-16 12:37:51 +08003622 new TInterfaceBlock(&blockName, fieldList, instanceName, blockLayoutQualifier);
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003623 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier);
3624 if (arrayIndex != nullptr)
3625 {
3626 interfaceBlockType.makeArray(arraySize);
3627 }
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003628
3629 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04003630 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003631
Jamie Madill98493dd2013-07-08 14:39:03 -04003632 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003633 {
3634 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04003635 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
3636 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003637 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05303638 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04003639
3640 // set parent pointer of the field variable
3641 fieldType->setInterfaceBlock(interfaceBlock);
3642
Olli Etuaho0f684632017-07-13 12:42:15 +03003643 TVariable *fieldVariable = symbolTable.declareVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04003644
Olli Etuaho0f684632017-07-13 12:42:15 +03003645 if (fieldVariable)
3646 {
3647 fieldVariable->setQualifier(typeQualifier.qualifier);
3648 }
3649 else
Arun Patole7e7e68d2015-05-22 12:02:25 +05303650 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003651 error(field->line(), "redefinition of an interface block member name",
3652 field->name().c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003653 }
3654 }
3655 }
3656 else
3657 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003658 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03003659
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003660 // add a symbol for this interface block
Olli Etuaho0f684632017-07-13 12:42:15 +03003661 TVariable *instanceTypeDef = symbolTable.declareVariable(instanceName, interfaceBlockType);
3662 if (instanceTypeDef)
3663 {
3664 instanceTypeDef->setQualifier(typeQualifier.qualifier);
3665 symbolId = instanceTypeDef->getUniqueId();
3666 }
3667 else
Arun Patole7e7e68d2015-05-22 12:02:25 +05303668 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003669 error(instanceLine, "redefinition of an interface block instance name",
3670 instanceName->c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003671 }
Olli Etuaho0f684632017-07-13 12:42:15 +03003672 symbolName = *instanceName;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003673 }
3674
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003675 TIntermSymbol *blockSymbol = new TIntermSymbol(symbolId, symbolName, interfaceBlockType);
3676 blockSymbol->setLine(typeQualifier.line);
Olli Etuaho13389b62016-10-16 11:48:18 +01003677 TIntermDeclaration *declaration = new TIntermDeclaration();
3678 declaration->appendDeclarator(blockSymbol);
3679 declaration->setLine(nameLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04003680
3681 exitStructDeclaration();
Olli Etuaho13389b62016-10-16 11:48:18 +01003682 return declaration;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003683}
3684
Olli Etuaho383b7912016-08-05 11:22:59 +03003685void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00003686{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003687 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003688
3689 // Embedded structure definitions are not supported per GLSL ES spec.
Olli Etuaho4de340a2016-12-16 09:32:03 +00003690 // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
Arun Patole7e7e68d2015-05-22 12:02:25 +05303691 if (mStructNestingLevel > 1)
3692 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003693 error(line, "Embedded struct definitions are not allowed", "struct");
kbr@chromium.org476541f2011-10-27 21:14:51 +00003694 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00003695}
3696
3697void TParseContext::exitStructDeclaration()
3698{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003699 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003700}
3701
Olli Etuaho8a176262016-08-16 14:23:01 +03003702void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00003703{
Jamie Madillacb4b812016-11-07 13:50:29 -05003704 if (!sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +05303705 {
Olli Etuaho8a176262016-08-16 14:23:01 +03003706 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003707 }
3708
Arun Patole7e7e68d2015-05-22 12:02:25 +05303709 if (field.type()->getBasicType() != EbtStruct)
3710 {
Olli Etuaho8a176262016-08-16 14:23:01 +03003711 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003712 }
3713
3714 // We're already inside a structure definition at this point, so add
3715 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05303716 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
3717 {
Jamie Madill41a49272014-03-18 16:10:13 -04003718 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003719 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
3720 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04003721 std::string reason = reasonStream.str();
Olli Etuaho4de340a2016-12-16 09:32:03 +00003722 error(line, reason.c_str(), field.name().c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03003723 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003724 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00003725}
3726
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003727//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003728// Parse an array index expression
3729//
Jamie Madillb98c3a82015-07-23 14:26:04 -04003730TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
3731 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303732 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003733{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003734 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
3735 {
3736 if (baseExpression->getAsSymbolNode())
3737 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303738 error(location, " left of '[' is not of type array, matrix, or vector ",
3739 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003740 }
3741 else
3742 {
3743 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
3744 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003745
Olli Etuaho3ec75682017-07-05 17:02:55 +03003746 return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003747 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003748
Jiawei Shaod8105a02017-08-08 09:54:36 +08003749 if (baseExpression->getQualifier() == EvqPerVertexIn)
3750 {
3751 ASSERT(mShaderType == GL_GEOMETRY_SHADER_OES);
3752 if (mGeometryShaderInputPrimitiveType == EptUndefined)
3753 {
3754 error(location, "missing input primitive declaration before indexing gl_in.", "[");
3755 return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
3756 }
3757 }
3758
Jamie Madill21c1e452014-12-29 11:33:41 -05003759 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
3760
Olli Etuaho36b05142015-11-12 13:10:42 +02003761 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
3762 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
3763 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
3764 // index is a constant expression.
3765 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
3766 {
3767 if (baseExpression->isInterfaceBlock())
3768 {
Jiawei Shaod8105a02017-08-08 09:54:36 +08003769 // TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
3770 switch (baseExpression->getQualifier())
3771 {
3772 case EvqPerVertexIn:
3773 break;
3774 case EvqUniform:
3775 case EvqBuffer:
3776 error(location,
3777 "array indexes for uniform block arrays and shader storage block arrays "
3778 "must be constant integral expressions",
3779 "[");
3780 break;
3781 default:
3782 UNREACHABLE();
3783 }
Olli Etuaho36b05142015-11-12 13:10:42 +02003784 }
3785 else if (baseExpression->getQualifier() == EvqFragmentOut)
3786 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003787 error(location,
3788 "array indexes for fragment outputs must be constant integral expressions", "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02003789 }
Olli Etuaho3e960462015-11-12 15:58:39 +02003790 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
3791 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003792 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3e960462015-11-12 15:58:39 +02003793 }
Olli Etuaho36b05142015-11-12 13:10:42 +02003794 }
3795
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003796 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04003797 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003798 // If an out-of-range index is not qualified as constant, the behavior in the spec is
3799 // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
3800 // constant fold expressions that are not constant expressions). The most compatible way to
3801 // handle this case is to report a warning instead of an error and force the index to be in
3802 // the correct range.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003803 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Olli Etuaho56229f12017-07-10 14:16:33 +03003804 int index = 0;
3805 if (indexConstantUnion->getBasicType() == EbtInt)
3806 {
3807 index = indexConstantUnion->getIConst(0);
3808 }
3809 else if (indexConstantUnion->getBasicType() == EbtUInt)
3810 {
3811 index = static_cast<int>(indexConstantUnion->getUConst(0));
3812 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003813
3814 int safeIndex = -1;
3815
3816 if (baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04003817 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003818 if (baseExpression->getQualifier() == EvqFragData && index > 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003819 {
Olli Etuahodaaff1c2017-07-05 18:03:26 +03003820 if (!isExtensionEnabled("GL_EXT_draw_buffers"))
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003821 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003822 outOfRangeError(outOfRangeIndexIsError, location,
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003823 "array index for gl_FragData must be zero when "
Olli Etuaho4de340a2016-12-16 09:32:03 +00003824 "GL_EXT_draw_buffers is disabled",
3825 "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003826 safeIndex = 0;
3827 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03003828 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003829 // Only do generic out-of-range check if similar error hasn't already been reported.
3830 if (safeIndex < 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003831 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003832 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003833 baseExpression->getOutermostArraySize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003834 "array index out of range");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003835 }
3836 }
3837 else if (baseExpression->isMatrix())
3838 {
3839 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
Olli Etuaho90892fb2016-07-14 14:44:51 +03003840 baseExpression->getType().getCols(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003841 "matrix field selection out of range");
Jamie Madill7164cf42013-07-08 13:30:59 -04003842 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003843 else if (baseExpression->isVector())
Jamie Madill7164cf42013-07-08 13:30:59 -04003844 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003845 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3846 baseExpression->getType().getNominalSize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003847 "vector field selection out of range");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003848 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003849
3850 ASSERT(safeIndex >= 0);
3851 // Data of constant unions can't be changed, because it may be shared with other
3852 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
3853 // sanitized object.
Olli Etuaho56229f12017-07-10 14:16:33 +03003854 if (safeIndex != index || indexConstantUnion->getBasicType() != EbtInt)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003855 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003856 TConstantUnion *safeConstantUnion = new TConstantUnion();
3857 safeConstantUnion->setIConst(safeIndex);
3858 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
Olli Etuaho56229f12017-07-10 14:16:33 +03003859 indexConstantUnion->getTypePointer()->setBasicType(EbtInt);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003860 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003861
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003862 TIntermBinary *node = new TIntermBinary(EOpIndexDirect, baseExpression, indexExpression);
3863 node->setLine(location);
3864 return node->fold(mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003865 }
Jamie Madill7164cf42013-07-08 13:30:59 -04003866 else
3867 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003868 TIntermBinary *node = new TIntermBinary(EOpIndexIndirect, baseExpression, indexExpression);
3869 node->setLine(location);
3870 // Indirect indexing can never be constant folded.
3871 return node;
Jamie Madill7164cf42013-07-08 13:30:59 -04003872 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003873}
3874
Olli Etuaho90892fb2016-07-14 14:44:51 +03003875int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
3876 const TSourceLoc &location,
3877 int index,
3878 int arraySize,
Olli Etuaho4de340a2016-12-16 09:32:03 +00003879 const char *reason)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003880{
3881 if (index >= arraySize || index < 0)
3882 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003883 std::stringstream reasonStream;
3884 reasonStream << reason << " '" << index << "'";
3885 std::string token = reasonStream.str();
3886 outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
Olli Etuaho90892fb2016-07-14 14:44:51 +03003887 if (index < 0)
3888 {
3889 return 0;
3890 }
3891 else
3892 {
3893 return arraySize - 1;
3894 }
3895 }
3896 return index;
3897}
3898
Jamie Madillb98c3a82015-07-23 14:26:04 -04003899TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
3900 const TSourceLoc &dotLocation,
3901 const TString &fieldString,
3902 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003903{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003904 if (baseExpression->isArray())
3905 {
3906 error(fieldLocation, "cannot apply dot operator to an array", ".");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003907 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003908 }
3909
3910 if (baseExpression->isVector())
3911 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003912 TVector<int> fieldOffsets;
3913 if (!parseVectorFields(fieldLocation, fieldString, baseExpression->getNominalSize(),
3914 &fieldOffsets))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003915 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003916 fieldOffsets.resize(1);
3917 fieldOffsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003918 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003919 TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldOffsets);
3920 node->setLine(dotLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003921
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003922 return node->fold();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003923 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003924 else if (baseExpression->getBasicType() == EbtStruct)
3925 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303926 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003927 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003928 {
3929 error(dotLocation, "structure has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003930 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003931 }
3932 else
3933 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003934 bool fieldFound = false;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003935 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003936 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003937 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003938 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003939 {
3940 fieldFound = true;
3941 break;
3942 }
3943 }
3944 if (fieldFound)
3945 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03003946 TIntermTyped *index = CreateIndexNode(i);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003947 index->setLine(fieldLocation);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003948 TIntermBinary *node =
3949 new TIntermBinary(EOpIndexDirectStruct, baseExpression, index);
3950 node->setLine(dotLocation);
3951 return node->fold(mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003952 }
3953 else
3954 {
3955 error(dotLocation, " no such field in structure", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003956 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003957 }
3958 }
3959 }
Jamie Madill98493dd2013-07-08 14:39:03 -04003960 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003961 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303962 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003963 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003964 {
3965 error(dotLocation, "interface block has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003966 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003967 }
3968 else
3969 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003970 bool fieldFound = false;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003971 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003972 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003973 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003974 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003975 {
3976 fieldFound = true;
3977 break;
3978 }
3979 }
3980 if (fieldFound)
3981 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03003982 TIntermTyped *index = CreateIndexNode(i);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003983 index->setLine(fieldLocation);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003984 TIntermBinary *node =
3985 new TIntermBinary(EOpIndexDirectInterfaceBlock, baseExpression, index);
3986 node->setLine(dotLocation);
3987 // Indexing interface blocks can never be constant folded.
3988 return node;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003989 }
3990 else
3991 {
3992 error(dotLocation, " no such field in interface block", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003993 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003994 }
3995 }
3996 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003997 else
3998 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003999 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004000 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03004001 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05304002 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004003 }
4004 else
4005 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05304006 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03004007 " field selection requires structure, vector, or interface block on left hand "
4008 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05304009 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004010 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004011 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004012 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004013}
4014
Jamie Madillb98c3a82015-07-23 14:26:04 -04004015TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
4016 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004017{
Martin Radev802abe02016-08-04 17:48:32 +03004018 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004019
4020 if (qualifierType == "shared")
4021 {
Jamie Madillacb4b812016-11-07 13:50:29 -05004022 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07004023 {
4024 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
4025 }
Jamie Madilla5efff92013-06-06 11:56:47 -04004026 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004027 }
4028 else if (qualifierType == "packed")
4029 {
Jamie Madillacb4b812016-11-07 13:50:29 -05004030 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07004031 {
4032 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
4033 }
Jamie Madilla5efff92013-06-06 11:56:47 -04004034 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004035 }
4036 else if (qualifierType == "std140")
4037 {
Jamie Madilla5efff92013-06-06 11:56:47 -04004038 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004039 }
4040 else if (qualifierType == "row_major")
4041 {
Jamie Madilla5efff92013-06-06 11:56:47 -04004042 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004043 }
4044 else if (qualifierType == "column_major")
4045 {
Jamie Madilla5efff92013-06-06 11:56:47 -04004046 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004047 }
4048 else if (qualifierType == "location")
4049 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00004050 error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
4051 qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004052 }
Andrei Volykhina5527072017-03-22 16:46:30 +03004053 else if (qualifierType == "yuv" && isExtensionEnabled("GL_EXT_YUV_target") &&
4054 mShaderType == GL_FRAGMENT_SHADER)
4055 {
4056 qualifier.yuv = true;
4057 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004058 else if (qualifierType == "rgba32f")
4059 {
4060 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4061 qualifier.imageInternalFormat = EiifRGBA32F;
4062 }
4063 else if (qualifierType == "rgba16f")
4064 {
4065 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4066 qualifier.imageInternalFormat = EiifRGBA16F;
4067 }
4068 else if (qualifierType == "r32f")
4069 {
4070 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4071 qualifier.imageInternalFormat = EiifR32F;
4072 }
4073 else if (qualifierType == "rgba8")
4074 {
4075 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4076 qualifier.imageInternalFormat = EiifRGBA8;
4077 }
4078 else if (qualifierType == "rgba8_snorm")
4079 {
4080 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4081 qualifier.imageInternalFormat = EiifRGBA8_SNORM;
4082 }
4083 else if (qualifierType == "rgba32i")
4084 {
4085 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4086 qualifier.imageInternalFormat = EiifRGBA32I;
4087 }
4088 else if (qualifierType == "rgba16i")
4089 {
4090 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4091 qualifier.imageInternalFormat = EiifRGBA16I;
4092 }
4093 else if (qualifierType == "rgba8i")
4094 {
4095 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4096 qualifier.imageInternalFormat = EiifRGBA8I;
4097 }
4098 else if (qualifierType == "r32i")
4099 {
4100 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4101 qualifier.imageInternalFormat = EiifR32I;
4102 }
4103 else if (qualifierType == "rgba32ui")
4104 {
4105 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4106 qualifier.imageInternalFormat = EiifRGBA32UI;
4107 }
4108 else if (qualifierType == "rgba16ui")
4109 {
4110 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4111 qualifier.imageInternalFormat = EiifRGBA16UI;
4112 }
4113 else if (qualifierType == "rgba8ui")
4114 {
4115 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4116 qualifier.imageInternalFormat = EiifRGBA8UI;
4117 }
4118 else if (qualifierType == "r32ui")
4119 {
4120 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4121 qualifier.imageInternalFormat = EiifR32UI;
4122 }
Shaob5cc1192017-07-06 10:47:20 +08004123 else if (qualifierType == "points" && isExtensionEnabled("GL_OES_geometry_shader") &&
4124 mShaderType == GL_GEOMETRY_SHADER_OES)
4125 {
4126 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4127 qualifier.primitiveType = EptPoints;
4128 }
4129 else if (qualifierType == "lines" && isExtensionEnabled("GL_OES_geometry_shader") &&
4130 mShaderType == GL_GEOMETRY_SHADER_OES)
4131 {
4132 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4133 qualifier.primitiveType = EptLines;
4134 }
4135 else if (qualifierType == "lines_adjacency" && isExtensionEnabled("GL_OES_geometry_shader") &&
4136 mShaderType == GL_GEOMETRY_SHADER_OES)
4137 {
4138 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4139 qualifier.primitiveType = EptLinesAdjacency;
4140 }
4141 else if (qualifierType == "triangles" && isExtensionEnabled("GL_OES_geometry_shader") &&
4142 mShaderType == GL_GEOMETRY_SHADER_OES)
4143 {
4144 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4145 qualifier.primitiveType = EptTriangles;
4146 }
4147 else if (qualifierType == "triangles_adjacency" &&
4148 isExtensionEnabled("GL_OES_geometry_shader") && mShaderType == GL_GEOMETRY_SHADER_OES)
4149 {
4150 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4151 qualifier.primitiveType = EptTrianglesAdjacency;
4152 }
4153 else if (qualifierType == "line_strip" && isExtensionEnabled("GL_OES_geometry_shader") &&
4154 mShaderType == GL_GEOMETRY_SHADER_OES)
4155 {
4156 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4157 qualifier.primitiveType = EptLineStrip;
4158 }
4159 else if (qualifierType == "triangle_strip" && isExtensionEnabled("GL_OES_geometry_shader") &&
4160 mShaderType == GL_GEOMETRY_SHADER_OES)
4161 {
4162 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4163 qualifier.primitiveType = EptTriangleStrip;
4164 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004165
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004166 else
4167 {
4168 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004169 }
4170
Jamie Madilla5efff92013-06-06 11:56:47 -04004171 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004172}
4173
Martin Radev802abe02016-08-04 17:48:32 +03004174void TParseContext::parseLocalSize(const TString &qualifierType,
4175 const TSourceLoc &qualifierTypeLine,
4176 int intValue,
4177 const TSourceLoc &intValueLine,
4178 const std::string &intValueString,
4179 size_t index,
Martin Radev4c4c8e72016-08-04 12:25:34 +03004180 sh::WorkGroupSize *localSize)
Martin Radev802abe02016-08-04 17:48:32 +03004181{
Olli Etuaho856c4972016-08-08 11:38:39 +03004182 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03004183 if (intValue < 1)
4184 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00004185 std::stringstream reasonStream;
4186 reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
4187 std::string reason = reasonStream.str();
4188 error(intValueLine, reason.c_str(), intValueString.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03004189 }
4190 (*localSize)[index] = intValue;
4191}
4192
Olli Etuaho09b04a22016-12-15 13:30:26 +00004193void TParseContext::parseNumViews(int intValue,
4194 const TSourceLoc &intValueLine,
4195 const std::string &intValueString,
4196 int *numViews)
4197{
4198 // This error is only specified in WebGL, but tightens unspecified behavior in the native
4199 // specification.
4200 if (intValue < 1)
4201 {
4202 error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
4203 }
4204 *numViews = intValue;
4205}
4206
Shaob5cc1192017-07-06 10:47:20 +08004207void TParseContext::parseInvocations(int intValue,
4208 const TSourceLoc &intValueLine,
4209 const std::string &intValueString,
4210 int *numInvocations)
4211{
4212 // Although SPEC isn't clear whether invocations can be less than 1, we add this limit because
4213 // it doesn't make sense to accept invocations <= 0.
4214 if (intValue < 1 || intValue > mMaxGeometryShaderInvocations)
4215 {
4216 error(intValueLine,
4217 "out of range: invocations must be in the range of [1, "
4218 "MAX_GEOMETRY_SHADER_INVOCATIONS_OES]",
4219 intValueString.c_str());
4220 }
4221 else
4222 {
4223 *numInvocations = intValue;
4224 }
4225}
4226
4227void TParseContext::parseMaxVertices(int intValue,
4228 const TSourceLoc &intValueLine,
4229 const std::string &intValueString,
4230 int *maxVertices)
4231{
4232 // Although SPEC isn't clear whether max_vertices can be less than 0, we add this limit because
4233 // it doesn't make sense to accept max_vertices < 0.
4234 if (intValue < 0 || intValue > mMaxGeometryShaderMaxVertices)
4235 {
4236 error(
4237 intValueLine,
4238 "out of range: max_vertices must be in the range of [0, gl_MaxGeometryOutputVertices]",
4239 intValueString.c_str());
4240 }
4241 else
4242 {
4243 *maxVertices = intValue;
4244 }
4245}
4246
Jamie Madillb98c3a82015-07-23 14:26:04 -04004247TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
4248 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04004249 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05304250 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004251{
Martin Radev802abe02016-08-04 17:48:32 +03004252 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004253
Martin Radev802abe02016-08-04 17:48:32 +03004254 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004255
Martin Radev802abe02016-08-04 17:48:32 +03004256 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004257 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04004258 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004259 if (intValue < 0)
4260 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00004261 error(intValueLine, "out of range: location must be non-negative",
4262 intValueString.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004263 }
4264 else
4265 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05004266 qualifier.location = intValue;
Olli Etuaho87d410c2016-09-05 13:33:26 +03004267 qualifier.locationsSpecified = 1;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004268 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004269 }
Olli Etuaho43364892017-02-13 16:00:12 +00004270 else if (qualifierType == "binding")
4271 {
4272 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4273 if (intValue < 0)
4274 {
4275 error(intValueLine, "out of range: binding must be non-negative",
4276 intValueString.c_str());
4277 }
4278 else
4279 {
4280 qualifier.binding = intValue;
4281 }
4282 }
jchen104cdac9e2017-05-08 11:01:20 +08004283 else if (qualifierType == "offset")
4284 {
4285 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4286 if (intValue < 0)
4287 {
4288 error(intValueLine, "out of range: offset must be non-negative",
4289 intValueString.c_str());
4290 }
4291 else
4292 {
4293 qualifier.offset = intValue;
4294 }
4295 }
Martin Radev802abe02016-08-04 17:48:32 +03004296 else if (qualifierType == "local_size_x")
4297 {
4298 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
4299 &qualifier.localSize);
4300 }
4301 else if (qualifierType == "local_size_y")
4302 {
4303 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
4304 &qualifier.localSize);
4305 }
4306 else if (qualifierType == "local_size_z")
4307 {
4308 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
4309 &qualifier.localSize);
4310 }
Olli Etuaho95468d12017-05-04 11:14:34 +03004311 else if (qualifierType == "num_views" && isMultiviewExtensionEnabled() &&
Olli Etuaho09b04a22016-12-15 13:30:26 +00004312 mShaderType == GL_VERTEX_SHADER)
4313 {
4314 parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
4315 }
Shaob5cc1192017-07-06 10:47:20 +08004316 else if (qualifierType == "invocations" && isExtensionEnabled("GL_OES_geometry_shader") &&
4317 mShaderType == GL_GEOMETRY_SHADER_OES)
4318 {
4319 parseInvocations(intValue, intValueLine, intValueString, &qualifier.invocations);
4320 }
4321 else if (qualifierType == "max_vertices" && isExtensionEnabled("GL_OES_geometry_shader") &&
4322 mShaderType == GL_GEOMETRY_SHADER_OES)
4323 {
4324 parseMaxVertices(intValue, intValueLine, intValueString, &qualifier.maxVertices);
4325 }
4326
Martin Radev802abe02016-08-04 17:48:32 +03004327 else
4328 {
4329 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03004330 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004331
Jamie Madilla5efff92013-06-06 11:56:47 -04004332 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004333}
4334
Olli Etuaho613b9592016-09-05 12:05:53 +03004335TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
4336{
4337 return new TTypeQualifierBuilder(
4338 new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
4339 mShaderVersion);
4340}
4341
Olli Etuahocce89652017-06-19 16:04:09 +03004342TStorageQualifierWrapper *TParseContext::parseGlobalStorageQualifier(TQualifier qualifier,
4343 const TSourceLoc &loc)
4344{
4345 checkIsAtGlobalLevel(loc, getQualifierString(qualifier));
4346 return new TStorageQualifierWrapper(qualifier, loc);
4347}
4348
4349TStorageQualifierWrapper *TParseContext::parseVaryingQualifier(const TSourceLoc &loc)
4350{
4351 if (getShaderType() == GL_VERTEX_SHADER)
4352 {
4353 return parseGlobalStorageQualifier(EvqVaryingOut, loc);
4354 }
4355 return parseGlobalStorageQualifier(EvqVaryingIn, loc);
4356}
4357
4358TStorageQualifierWrapper *TParseContext::parseInQualifier(const TSourceLoc &loc)
4359{
4360 if (declaringFunction())
4361 {
4362 return new TStorageQualifierWrapper(EvqIn, loc);
4363 }
Shaob5cc1192017-07-06 10:47:20 +08004364
4365 switch (getShaderType())
Olli Etuahocce89652017-06-19 16:04:09 +03004366 {
Shaob5cc1192017-07-06 10:47:20 +08004367 case GL_VERTEX_SHADER:
Olli Etuahocce89652017-06-19 16:04:09 +03004368 {
Shaob5cc1192017-07-06 10:47:20 +08004369 if (mShaderVersion < 300 && !isMultiviewExtensionEnabled())
4370 {
4371 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
4372 }
4373 return new TStorageQualifierWrapper(EvqVertexIn, loc);
Olli Etuahocce89652017-06-19 16:04:09 +03004374 }
Shaob5cc1192017-07-06 10:47:20 +08004375 case GL_FRAGMENT_SHADER:
Olli Etuahocce89652017-06-19 16:04:09 +03004376 {
Shaob5cc1192017-07-06 10:47:20 +08004377 if (mShaderVersion < 300)
4378 {
4379 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
4380 }
4381 return new TStorageQualifierWrapper(EvqFragmentIn, loc);
Olli Etuahocce89652017-06-19 16:04:09 +03004382 }
Shaob5cc1192017-07-06 10:47:20 +08004383 case GL_COMPUTE_SHADER:
4384 {
4385 return new TStorageQualifierWrapper(EvqComputeIn, loc);
4386 }
4387 case GL_GEOMETRY_SHADER_OES:
4388 {
4389 return new TStorageQualifierWrapper(EvqGeometryIn, loc);
4390 }
4391 default:
4392 {
4393 UNREACHABLE();
4394 return new TStorageQualifierWrapper(EvqLast, loc);
4395 }
Olli Etuahocce89652017-06-19 16:04:09 +03004396 }
Olli Etuahocce89652017-06-19 16:04:09 +03004397}
4398
4399TStorageQualifierWrapper *TParseContext::parseOutQualifier(const TSourceLoc &loc)
4400{
4401 if (declaringFunction())
4402 {
4403 return new TStorageQualifierWrapper(EvqOut, loc);
4404 }
Shaob5cc1192017-07-06 10:47:20 +08004405 switch (getShaderType())
Olli Etuahocce89652017-06-19 16:04:09 +03004406 {
Shaob5cc1192017-07-06 10:47:20 +08004407 case GL_VERTEX_SHADER:
4408 {
4409 if (mShaderVersion < 300)
4410 {
4411 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
4412 }
4413 return new TStorageQualifierWrapper(EvqVertexOut, loc);
4414 }
4415 case GL_FRAGMENT_SHADER:
4416 {
4417 if (mShaderVersion < 300)
4418 {
4419 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
4420 }
4421 return new TStorageQualifierWrapper(EvqFragmentOut, loc);
4422 }
4423 case GL_COMPUTE_SHADER:
4424 {
4425 error(loc, "storage qualifier isn't supported in compute shaders", "out");
4426 return new TStorageQualifierWrapper(EvqLast, loc);
4427 }
4428 case GL_GEOMETRY_SHADER_OES:
4429 {
4430 return new TStorageQualifierWrapper(EvqGeometryOut, loc);
4431 }
4432 default:
4433 {
4434 UNREACHABLE();
4435 return new TStorageQualifierWrapper(EvqLast, loc);
4436 }
Olli Etuahocce89652017-06-19 16:04:09 +03004437 }
Olli Etuahocce89652017-06-19 16:04:09 +03004438}
4439
4440TStorageQualifierWrapper *TParseContext::parseInOutQualifier(const TSourceLoc &loc)
4441{
4442 if (!declaringFunction())
4443 {
4444 error(loc, "invalid qualifier: can be only used with function parameters", "inout");
4445 }
4446 return new TStorageQualifierWrapper(EvqInOut, loc);
4447}
4448
Jamie Madillb98c3a82015-07-23 14:26:04 -04004449TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03004450 TLayoutQualifier rightQualifier,
4451 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004452{
Martin Radevc28888b2016-07-22 15:27:42 +03004453 return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
Olli Etuaho77ba4082016-12-16 12:01:18 +00004454 mDiagnostics);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004455}
4456
Olli Etuahocce89652017-06-19 16:04:09 +03004457TField *TParseContext::parseStructDeclarator(TString *identifier, const TSourceLoc &loc)
4458{
4459 checkIsNotReserved(loc, *identifier);
4460 TType *type = new TType(EbtVoid, EbpUndefined);
4461 return new TField(type, identifier, loc);
4462}
4463
4464TField *TParseContext::parseStructArrayDeclarator(TString *identifier,
4465 const TSourceLoc &loc,
4466 TIntermTyped *arraySize,
4467 const TSourceLoc &arraySizeLoc)
4468{
4469 checkIsNotReserved(loc, *identifier);
4470
4471 TType *type = new TType(EbtVoid, EbpUndefined);
4472 unsigned int size = checkIsValidArraySize(arraySizeLoc, arraySize);
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004473 type->makeArray(size);
Olli Etuahocce89652017-06-19 16:04:09 +03004474
4475 return new TField(type, identifier, loc);
4476}
4477
Olli Etuaho4de340a2016-12-16 09:32:03 +00004478TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
4479 const TFieldList *newlyAddedFields,
4480 const TSourceLoc &location)
4481{
4482 for (TField *field : *newlyAddedFields)
4483 {
4484 for (TField *oldField : *processedFields)
4485 {
4486 if (oldField->name() == field->name())
4487 {
4488 error(location, "duplicate field name in structure", field->name().c_str());
4489 }
4490 }
4491 processedFields->push_back(field);
4492 }
4493 return processedFields;
4494}
4495
Martin Radev70866b82016-07-22 15:27:42 +03004496TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
4497 const TTypeQualifierBuilder &typeQualifierBuilder,
4498 TPublicType *typeSpecifier,
4499 TFieldList *fieldList)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04004500{
Olli Etuaho77ba4082016-12-16 12:01:18 +00004501 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04004502
Martin Radev70866b82016-07-22 15:27:42 +03004503 typeSpecifier->qualifier = typeQualifier.qualifier;
4504 typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03004505 typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03004506 typeSpecifier->invariant = typeQualifier.invariant;
4507 if (typeQualifier.precision != EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +05304508 {
Martin Radev70866b82016-07-22 15:27:42 +03004509 typeSpecifier->precision = typeQualifier.precision;
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04004510 }
Martin Radev70866b82016-07-22 15:27:42 +03004511 return addStructDeclaratorList(*typeSpecifier, fieldList);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04004512}
4513
Jamie Madillb98c3a82015-07-23 14:26:04 -04004514TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004515 TFieldList *declaratorList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004516{
Martin Radev4a9cd802016-09-01 16:51:51 +03004517 checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
4518 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03004519
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004520 checkIsNonVoid(typeSpecifier.getLine(), (*declaratorList)[0]->name(),
4521 typeSpecifier.getBasicType());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004522
Martin Radev4a9cd802016-09-01 16:51:51 +03004523 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03004524
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004525 for (unsigned int i = 0; i < declaratorList->size(); ++i)
Arun Patole7e7e68d2015-05-22 12:02:25 +05304526 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004527 auto declaratorArraySizes = (*declaratorList)[i]->type()->getArraySizes();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004528 // don't allow arrays of arrays
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004529 if (!declaratorArraySizes.empty())
Arun Patole7e7e68d2015-05-22 12:02:25 +05304530 {
Martin Radev4a9cd802016-09-01 16:51:51 +03004531 checkIsValidTypeForArray(typeSpecifier.getLine(), typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004532 }
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004533
4534 TType *type = (*declaratorList)[i]->type();
4535 *type = TType(typeSpecifier);
4536 for (unsigned int arraySize : declaratorArraySizes)
Arun Patole7e7e68d2015-05-22 12:02:25 +05304537 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004538 type->makeArray(arraySize);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004539 }
4540
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004541 checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*declaratorList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004542 }
4543
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004544 return declaratorList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004545}
4546
Martin Radev4a9cd802016-09-01 16:51:51 +03004547TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
4548 const TSourceLoc &nameLine,
4549 const TString *structName,
4550 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004551{
Olli Etuahoa5e693a2017-07-13 16:07:26 +03004552 TStructure *structure = new TStructure(&symbolTable, structName, fieldList);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004553
Jamie Madill9b820842015-02-12 10:40:10 -05004554 // Store a bool in the struct if we're at global scope, to allow us to
4555 // skip the local struct scoping workaround in HLSL.
Jamie Madill9b820842015-02-12 10:40:10 -05004556 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04004557
Jamie Madill98493dd2013-07-08 14:39:03 -04004558 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004559 {
Olli Etuaho856c4972016-08-08 11:38:39 +03004560 checkIsNotReserved(nameLine, *structName);
Olli Etuaho0f684632017-07-13 12:42:15 +03004561 if (!symbolTable.declareStructType(structure))
Arun Patole7e7e68d2015-05-22 12:02:25 +05304562 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00004563 error(nameLine, "redefinition of a struct", structName->c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004564 }
4565 }
4566
4567 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04004568 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004569 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004570 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04004571 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004572 switch (qualifier)
4573 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004574 case EvqGlobal:
4575 case EvqTemporary:
4576 break;
4577 default:
4578 error(field.line(), "invalid qualifier on struct member",
4579 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04004580 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004581 }
Martin Radev70866b82016-07-22 15:27:42 +03004582 if (field.type()->isInvariant())
4583 {
4584 error(field.line(), "invalid qualifier on struct member", "invariant");
4585 }
jchen104cdac9e2017-05-08 11:01:20 +08004586 // ESSL 3.10 section 4.1.8 -- atomic_uint or images are not allowed as structure member.
4587 if (IsImage(field.type()->getBasicType()) || IsAtomicCounter(field.type()->getBasicType()))
Martin Radev2cc85b32016-08-05 16:22:53 +03004588 {
4589 error(field.line(), "disallowed type in struct", field.type()->getBasicString());
4590 }
4591
Olli Etuaho43364892017-02-13 16:00:12 +00004592 checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
4593
4594 checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);
Martin Radev70866b82016-07-22 15:27:42 +03004595
4596 checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004597 }
4598
Martin Radev4a9cd802016-09-01 16:51:51 +03004599 TTypeSpecifierNonArray typeSpecifierNonArray;
Olli Etuaho0f684632017-07-13 12:42:15 +03004600 typeSpecifierNonArray.initializeStruct(structure, true, structLine);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004601 exitStructDeclaration();
4602
Martin Radev4a9cd802016-09-01 16:51:51 +03004603 return typeSpecifierNonArray;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004604}
4605
Jamie Madillb98c3a82015-07-23 14:26:04 -04004606TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01004607 TIntermBlock *statementList,
Jamie Madillb98c3a82015-07-23 14:26:04 -04004608 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02004609{
Olli Etuaho53f076f2015-02-20 10:55:14 +02004610 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04004611 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02004612 init->isVector())
4613 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004614 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
4615 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004616 return nullptr;
4617 }
4618
Olli Etuahoac5274d2015-02-20 10:19:08 +02004619 if (statementList)
4620 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00004621 if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
Olli Etuahoac5274d2015-02-20 10:19:08 +02004622 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02004623 return nullptr;
4624 }
4625 }
4626
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004627 TIntermSwitch *node = new TIntermSwitch(init, statementList);
4628 node->setLine(loc);
Olli Etuahoa3a36662015-02-17 13:46:51 +02004629 return node;
4630}
4631
4632TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
4633{
Olli Etuaho53f076f2015-02-20 10:55:14 +02004634 if (mSwitchNestingLevel == 0)
4635 {
4636 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004637 return nullptr;
4638 }
4639 if (condition == nullptr)
4640 {
4641 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004642 return nullptr;
4643 }
4644 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04004645 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02004646 {
4647 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004648 }
4649 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02004650 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
4651 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
4652 // fold in case labels.
4653 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02004654 {
4655 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004656 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004657 TIntermCase *node = new TIntermCase(condition);
4658 node->setLine(loc);
Olli Etuahoa3a36662015-02-17 13:46:51 +02004659 return node;
4660}
4661
4662TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
4663{
Olli Etuaho53f076f2015-02-20 10:55:14 +02004664 if (mSwitchNestingLevel == 0)
4665 {
4666 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004667 return nullptr;
4668 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004669 TIntermCase *node = new TIntermCase(nullptr);
4670 node->setLine(loc);
Olli Etuahoa3a36662015-02-17 13:46:51 +02004671 return node;
4672}
4673
Jamie Madillb98c3a82015-07-23 14:26:04 -04004674TIntermTyped *TParseContext::createUnaryMath(TOperator op,
4675 TIntermTyped *child,
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004676 const TSourceLoc &loc)
Olli Etuaho69c11b52015-03-26 12:59:00 +02004677{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004678 ASSERT(child != nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02004679
4680 switch (op)
4681 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004682 case EOpLogicalNot:
4683 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
4684 child->isVector())
4685 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004686 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004687 return nullptr;
4688 }
4689 break;
4690 case EOpBitwiseNot:
4691 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
4692 child->isMatrix() || child->isArray())
4693 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004694 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004695 return nullptr;
4696 }
4697 break;
4698 case EOpPostIncrement:
4699 case EOpPreIncrement:
4700 case EOpPostDecrement:
4701 case EOpPreDecrement:
4702 case EOpNegative:
4703 case EOpPositive:
Olli Etuaho94050052017-05-08 14:17:44 +03004704 if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() ||
4705 child->getBasicType() == EbtBool || child->isArray() ||
4706 IsOpaqueType(child->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -04004707 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004708 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004709 return nullptr;
4710 }
4711 // Operators for built-ins are already type checked against their prototype.
4712 default:
4713 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02004714 }
4715
Jiajia Qinbc585152017-06-23 15:42:17 +08004716 if (child->getMemoryQualifier().writeonly)
4717 {
4718 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
4719 return nullptr;
4720 }
4721
Olli Etuahof119a262016-08-19 15:54:22 +03004722 TIntermUnary *node = new TIntermUnary(op, child);
4723 node->setLine(loc);
Olli Etuahof119a262016-08-19 15:54:22 +03004724
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004725 return node->fold(mDiagnostics);
Olli Etuaho69c11b52015-03-26 12:59:00 +02004726}
4727
Olli Etuaho09b22472015-02-11 11:47:26 +02004728TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
4729{
Olli Etuahocce89652017-06-19 16:04:09 +03004730 ASSERT(op != EOpNull);
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004731 TIntermTyped *node = createUnaryMath(op, child, loc);
Olli Etuaho69c11b52015-03-26 12:59:00 +02004732 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02004733 {
Olli Etuaho09b22472015-02-11 11:47:26 +02004734 return child;
4735 }
4736 return node;
4737}
4738
Jamie Madillb98c3a82015-07-23 14:26:04 -04004739TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
4740 TIntermTyped *child,
4741 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004742{
Olli Etuaho856c4972016-08-08 11:38:39 +03004743 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02004744 return addUnaryMath(op, child, loc);
4745}
4746
Jamie Madillb98c3a82015-07-23 14:26:04 -04004747bool TParseContext::binaryOpCommonCheck(TOperator op,
4748 TIntermTyped *left,
4749 TIntermTyped *right,
4750 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004751{
jchen10b4cf5652017-05-05 18:51:17 +08004752 // Check opaque types are not allowed to be operands in expressions other than array indexing
4753 // and structure member selection.
4754 if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType()))
4755 {
4756 switch (op)
4757 {
4758 case EOpIndexDirect:
4759 case EOpIndexIndirect:
4760 break;
4761 case EOpIndexDirectStruct:
4762 UNREACHABLE();
4763
4764 default:
4765 error(loc, "Invalid operation for variables with an opaque type",
4766 GetOperatorString(op));
4767 return false;
4768 }
4769 }
jchen10cc2a10e2017-05-03 14:05:12 +08004770
Jiajia Qinbc585152017-06-23 15:42:17 +08004771 if (right->getMemoryQualifier().writeonly)
4772 {
4773 error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op));
4774 return false;
4775 }
4776
4777 if (left->getMemoryQualifier().writeonly)
4778 {
4779 switch (op)
4780 {
4781 case EOpAssign:
4782 case EOpInitialize:
4783 case EOpIndexDirect:
4784 case EOpIndexIndirect:
4785 case EOpIndexDirectStruct:
4786 case EOpIndexDirectInterfaceBlock:
4787 break;
4788 default:
4789 error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op));
4790 return false;
4791 }
4792 }
4793
Olli Etuaho244be012016-08-18 15:26:02 +03004794 if (left->getType().getStruct() || right->getType().getStruct())
4795 {
4796 switch (op)
4797 {
4798 case EOpIndexDirectStruct:
4799 ASSERT(left->getType().getStruct());
4800 break;
4801 case EOpEqual:
4802 case EOpNotEqual:
4803 case EOpAssign:
4804 case EOpInitialize:
4805 if (left->getType() != right->getType())
4806 {
4807 return false;
4808 }
4809 break;
4810 default:
4811 error(loc, "Invalid operation for structs", GetOperatorString(op));
4812 return false;
4813 }
4814 }
4815
Olli Etuaho94050052017-05-08 14:17:44 +03004816 if (left->isInterfaceBlock() || right->isInterfaceBlock())
4817 {
4818 switch (op)
4819 {
4820 case EOpIndexDirectInterfaceBlock:
4821 ASSERT(left->getType().getInterfaceBlock());
4822 break;
4823 default:
4824 error(loc, "Invalid operation for interface blocks", GetOperatorString(op));
4825 return false;
4826 }
4827 }
4828
Olli Etuahod6b14282015-03-17 14:31:35 +02004829 if (left->isArray() || right->isArray())
4830 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004831 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02004832 {
4833 error(loc, "Invalid operation for arrays", GetOperatorString(op));
4834 return false;
4835 }
4836
4837 if (left->isArray() != right->isArray())
4838 {
4839 error(loc, "array / non-array mismatch", GetOperatorString(op));
4840 return false;
4841 }
4842
4843 switch (op)
4844 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004845 case EOpEqual:
4846 case EOpNotEqual:
4847 case EOpAssign:
4848 case EOpInitialize:
4849 break;
4850 default:
4851 error(loc, "Invalid operation for arrays", GetOperatorString(op));
4852 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02004853 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03004854 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004855 if (left->getType().getArraySizes() != right->getType().getArraySizes())
Olli Etuahoe79904c2015-03-18 16:56:42 +02004856 {
4857 error(loc, "array size mismatch", GetOperatorString(op));
4858 return false;
4859 }
Olli Etuahod6b14282015-03-17 14:31:35 +02004860 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004861
4862 // Check ops which require integer / ivec parameters
4863 bool isBitShift = false;
4864 switch (op)
4865 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004866 case EOpBitShiftLeft:
4867 case EOpBitShiftRight:
4868 case EOpBitShiftLeftAssign:
4869 case EOpBitShiftRightAssign:
4870 // Unsigned can be bit-shifted by signed and vice versa, but we need to
4871 // check that the basic type is an integer type.
4872 isBitShift = true;
4873 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
4874 {
4875 return false;
4876 }
4877 break;
4878 case EOpBitwiseAnd:
4879 case EOpBitwiseXor:
4880 case EOpBitwiseOr:
4881 case EOpBitwiseAndAssign:
4882 case EOpBitwiseXorAssign:
4883 case EOpBitwiseOrAssign:
4884 // It is enough to check the type of only one operand, since later it
4885 // is checked that the operand types match.
4886 if (!IsInteger(left->getBasicType()))
4887 {
4888 return false;
4889 }
4890 break;
4891 default:
4892 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004893 }
4894
4895 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
4896 // So the basic type should usually match.
4897 if (!isBitShift && left->getBasicType() != right->getBasicType())
4898 {
4899 return false;
4900 }
4901
Olli Etuaho63e1ec52016-08-18 22:05:12 +03004902 // Check that:
4903 // 1. Type sizes match exactly on ops that require that.
4904 // 2. Restrictions for structs that contain arrays or samplers are respected.
4905 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
Jamie Madillb98c3a82015-07-23 14:26:04 -04004906 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004907 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004908 case EOpAssign:
4909 case EOpInitialize:
4910 case EOpEqual:
4911 case EOpNotEqual:
4912 // ESSL 1.00 sections 5.7, 5.8, 5.9
4913 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
4914 {
4915 error(loc, "undefined operation for structs containing arrays",
4916 GetOperatorString(op));
4917 return false;
4918 }
4919 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
4920 // we interpret the spec so that this extends to structs containing samplers,
4921 // similarly to ESSL 1.00 spec.
4922 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
4923 left->getType().isStructureContainingSamplers())
4924 {
4925 error(loc, "undefined operation for structs containing samplers",
4926 GetOperatorString(op));
4927 return false;
4928 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004929
Olli Etuahoe1805592017-01-02 16:41:20 +00004930 if ((left->getNominalSize() != right->getNominalSize()) ||
4931 (left->getSecondarySize() != right->getSecondarySize()))
4932 {
4933 error(loc, "dimension mismatch", GetOperatorString(op));
4934 return false;
4935 }
4936 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004937 case EOpLessThan:
4938 case EOpGreaterThan:
4939 case EOpLessThanEqual:
4940 case EOpGreaterThanEqual:
Olli Etuahoe1805592017-01-02 16:41:20 +00004941 if (!left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04004942 {
Olli Etuahoe1805592017-01-02 16:41:20 +00004943 error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
Jamie Madillb98c3a82015-07-23 14:26:04 -04004944 return false;
4945 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03004946 break;
4947 case EOpAdd:
4948 case EOpSub:
4949 case EOpDiv:
4950 case EOpIMod:
4951 case EOpBitShiftLeft:
4952 case EOpBitShiftRight:
4953 case EOpBitwiseAnd:
4954 case EOpBitwiseXor:
4955 case EOpBitwiseOr:
4956 case EOpAddAssign:
4957 case EOpSubAssign:
4958 case EOpDivAssign:
4959 case EOpIModAssign:
4960 case EOpBitShiftLeftAssign:
4961 case EOpBitShiftRightAssign:
4962 case EOpBitwiseAndAssign:
4963 case EOpBitwiseXorAssign:
4964 case EOpBitwiseOrAssign:
4965 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
4966 {
4967 return false;
4968 }
4969
4970 // Are the sizes compatible?
4971 if (left->getNominalSize() != right->getNominalSize() ||
4972 left->getSecondarySize() != right->getSecondarySize())
4973 {
4974 // If the nominal sizes of operands do not match:
4975 // One of them must be a scalar.
4976 if (!left->isScalar() && !right->isScalar())
4977 return false;
4978
4979 // In the case of compound assignment other than multiply-assign,
4980 // the right side needs to be a scalar. Otherwise a vector/matrix
4981 // would be assigned to a scalar. A scalar can't be shifted by a
4982 // vector either.
4983 if (!right->isScalar() &&
4984 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
4985 return false;
4986 }
4987 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004988 default:
4989 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004990 }
4991
Olli Etuahod6b14282015-03-17 14:31:35 +02004992 return true;
4993}
4994
Olli Etuaho1dded802016-08-18 18:13:13 +03004995bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
4996 const TType &left,
4997 const TType &right)
4998{
4999 switch (op)
5000 {
5001 case EOpMul:
5002 case EOpMulAssign:
5003 return left.getNominalSize() == right.getNominalSize() &&
5004 left.getSecondarySize() == right.getSecondarySize();
5005 case EOpVectorTimesScalar:
5006 return true;
5007 case EOpVectorTimesScalarAssign:
5008 ASSERT(!left.isMatrix() && !right.isMatrix());
5009 return left.isVector() && !right.isVector();
5010 case EOpVectorTimesMatrix:
5011 return left.getNominalSize() == right.getRows();
5012 case EOpVectorTimesMatrixAssign:
5013 ASSERT(!left.isMatrix() && right.isMatrix());
5014 return left.isVector() && left.getNominalSize() == right.getRows() &&
5015 left.getNominalSize() == right.getCols();
5016 case EOpMatrixTimesVector:
5017 return left.getCols() == right.getNominalSize();
5018 case EOpMatrixTimesScalar:
5019 return true;
5020 case EOpMatrixTimesScalarAssign:
5021 ASSERT(left.isMatrix() && !right.isMatrix());
5022 return !right.isVector();
5023 case EOpMatrixTimesMatrix:
5024 return left.getCols() == right.getRows();
5025 case EOpMatrixTimesMatrixAssign:
5026 ASSERT(left.isMatrix() && right.isMatrix());
5027 // We need to check two things:
5028 // 1. The matrix multiplication step is valid.
5029 // 2. The result will have the same number of columns as the lvalue.
5030 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
5031
5032 default:
5033 UNREACHABLE();
5034 return false;
5035 }
5036}
5037
Jamie Madillb98c3a82015-07-23 14:26:04 -04005038TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
5039 TIntermTyped *left,
5040 TIntermTyped *right,
5041 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02005042{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02005043 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02005044 return nullptr;
5045
Olli Etuahofc1806e2015-03-17 13:03:11 +02005046 switch (op)
5047 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04005048 case EOpEqual:
5049 case EOpNotEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04005050 case EOpLessThan:
5051 case EOpGreaterThan:
5052 case EOpLessThanEqual:
5053 case EOpGreaterThanEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04005054 break;
5055 case EOpLogicalOr:
5056 case EOpLogicalXor:
5057 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03005058 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
5059 !right->getType().getStruct());
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00005060 if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04005061 {
5062 return nullptr;
5063 }
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00005064 // Basic types matching should have been already checked.
5065 ASSERT(right->getBasicType() == EbtBool);
Jamie Madillb98c3a82015-07-23 14:26:04 -04005066 break;
5067 case EOpAdd:
5068 case EOpSub:
5069 case EOpDiv:
5070 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03005071 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
5072 !right->getType().getStruct());
5073 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04005074 {
5075 return nullptr;
5076 }
5077 break;
5078 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03005079 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
5080 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04005081 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03005082 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04005083 {
5084 return nullptr;
5085 }
5086 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04005087 default:
5088 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02005089 }
5090
Olli Etuaho1dded802016-08-18 18:13:13 +03005091 if (op == EOpMul)
5092 {
5093 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
5094 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
5095 {
5096 return nullptr;
5097 }
5098 }
5099
Olli Etuaho3fdec912016-08-18 15:08:06 +03005100 TIntermBinary *node = new TIntermBinary(op, left, right);
5101 node->setLine(loc);
5102
Olli Etuaho3fdec912016-08-18 15:08:06 +03005103 // See if we can fold constants.
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03005104 return node->fold(mDiagnostics);
Olli Etuahofc1806e2015-03-17 13:03:11 +02005105}
5106
Jamie Madillb98c3a82015-07-23 14:26:04 -04005107TIntermTyped *TParseContext::addBinaryMath(TOperator op,
5108 TIntermTyped *left,
5109 TIntermTyped *right,
5110 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02005111{
Olli Etuahofc1806e2015-03-17 13:03:11 +02005112 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02005113 if (node == 0)
5114 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04005115 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
5116 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02005117 return left;
5118 }
5119 return node;
5120}
5121
Jamie Madillb98c3a82015-07-23 14:26:04 -04005122TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
5123 TIntermTyped *left,
5124 TIntermTyped *right,
5125 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02005126{
Olli Etuahofc1806e2015-03-17 13:03:11 +02005127 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho56229f12017-07-10 14:16:33 +03005128 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02005129 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04005130 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
5131 right->getCompleteString());
Olli Etuaho3ec75682017-07-05 17:02:55 +03005132 node = CreateBoolNode(false);
Olli Etuaho56229f12017-07-10 14:16:33 +03005133 node->setLine(loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02005134 }
5135 return node;
5136}
5137
Olli Etuaho13389b62016-10-16 11:48:18 +01005138TIntermBinary *TParseContext::createAssign(TOperator op,
5139 TIntermTyped *left,
5140 TIntermTyped *right,
5141 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02005142{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02005143 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02005144 {
Olli Etuaho1dded802016-08-18 18:13:13 +03005145 if (op == EOpMulAssign)
5146 {
5147 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
5148 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
5149 {
5150 return nullptr;
5151 }
5152 }
Olli Etuaho3fdec912016-08-18 15:08:06 +03005153 TIntermBinary *node = new TIntermBinary(op, left, right);
5154 node->setLine(loc);
5155
Olli Etuaho3fdec912016-08-18 15:08:06 +03005156 return node;
Olli Etuahod6b14282015-03-17 14:31:35 +02005157 }
5158 return nullptr;
5159}
5160
Jamie Madillb98c3a82015-07-23 14:26:04 -04005161TIntermTyped *TParseContext::addAssign(TOperator op,
5162 TIntermTyped *left,
5163 TIntermTyped *right,
5164 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02005165{
Olli Etuahocce89652017-06-19 16:04:09 +03005166 checkCanBeLValue(loc, "assign", left);
Olli Etuahod6b14282015-03-17 14:31:35 +02005167 TIntermTyped *node = createAssign(op, left, right, loc);
5168 if (node == nullptr)
5169 {
5170 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02005171 return left;
5172 }
5173 return node;
5174}
5175
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02005176TIntermTyped *TParseContext::addComma(TIntermTyped *left,
5177 TIntermTyped *right,
5178 const TSourceLoc &loc)
5179{
Corentin Wallez0d959252016-07-12 17:26:32 -04005180 // WebGL2 section 5.26, the following results in an error:
5181 // "Sequence operator applied to void, arrays, or structs containing arrays"
Jamie Madilld7b1ab52016-12-12 14:42:19 -05005182 if (mShaderSpec == SH_WEBGL2_SPEC &&
5183 (left->isArray() || left->getBasicType() == EbtVoid ||
5184 left->getType().isStructureContainingArrays() || right->isArray() ||
5185 right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
Corentin Wallez0d959252016-07-12 17:26:32 -04005186 {
5187 error(loc,
5188 "sequence operator is not allowed for void, arrays, or structs containing arrays",
5189 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04005190 }
5191
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03005192 TIntermBinary *commaNode = new TIntermBinary(EOpComma, left, right);
5193 TQualifier resultQualifier = TIntermBinary::GetCommaQualifier(mShaderVersion, left, right);
5194 commaNode->getTypePointer()->setQualifier(resultQualifier);
5195 return commaNode->fold(mDiagnostics);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02005196}
5197
Olli Etuaho49300862015-02-20 14:54:49 +02005198TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
5199{
5200 switch (op)
5201 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04005202 case EOpContinue:
5203 if (mLoopNestingLevel <= 0)
5204 {
5205 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04005206 }
5207 break;
5208 case EOpBreak:
5209 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
5210 {
5211 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04005212 }
5213 break;
5214 case EOpReturn:
5215 if (mCurrentFunctionType->getBasicType() != EbtVoid)
5216 {
5217 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04005218 }
5219 break;
Olli Etuahocce89652017-06-19 16:04:09 +03005220 case EOpKill:
5221 if (mShaderType != GL_FRAGMENT_SHADER)
5222 {
5223 error(loc, "discard supported in fragment shaders only", "discard");
5224 }
5225 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04005226 default:
Olli Etuahocce89652017-06-19 16:04:09 +03005227 UNREACHABLE();
Jamie Madillb98c3a82015-07-23 14:26:04 -04005228 break;
Olli Etuaho49300862015-02-20 14:54:49 +02005229 }
Olli Etuahocce89652017-06-19 16:04:09 +03005230 return addBranch(op, nullptr, loc);
Olli Etuaho49300862015-02-20 14:54:49 +02005231}
5232
Jamie Madillb98c3a82015-07-23 14:26:04 -04005233TIntermBranch *TParseContext::addBranch(TOperator op,
Olli Etuahocce89652017-06-19 16:04:09 +03005234 TIntermTyped *expression,
Jamie Madillb98c3a82015-07-23 14:26:04 -04005235 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02005236{
Olli Etuahocce89652017-06-19 16:04:09 +03005237 if (expression != nullptr)
Olli Etuaho49300862015-02-20 14:54:49 +02005238 {
Olli Etuahocce89652017-06-19 16:04:09 +03005239 ASSERT(op == EOpReturn);
5240 mFunctionReturnsValue = true;
5241 if (mCurrentFunctionType->getBasicType() == EbtVoid)
5242 {
5243 error(loc, "void function cannot return a value", "return");
5244 }
5245 else if (*mCurrentFunctionType != expression->getType())
5246 {
5247 error(loc, "function return is not matching type:", "return");
5248 }
Olli Etuaho49300862015-02-20 14:54:49 +02005249 }
Olli Etuahocce89652017-06-19 16:04:09 +03005250 TIntermBranch *node = new TIntermBranch(op, expression);
5251 node->setLine(loc);
5252 return node;
Olli Etuaho49300862015-02-20 14:54:49 +02005253}
5254
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005255void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
5256{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08005257 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Olli Etuahobd674552016-10-06 13:28:42 +01005258 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005259 TIntermNode *offset = nullptr;
5260 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuahoec9232b2017-03-27 17:01:37 +03005261 if (name == "texelFetchOffset" || name == "textureLodOffset" ||
5262 name == "textureProjLodOffset" || name == "textureGradOffset" ||
5263 name == "textureProjGradOffset")
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005264 {
5265 offset = arguments->back();
5266 }
Olli Etuahoec9232b2017-03-27 17:01:37 +03005267 else if (name == "textureOffset" || name == "textureProjOffset")
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005268 {
5269 // A bias parameter might follow the offset parameter.
5270 ASSERT(arguments->size() >= 3);
5271 offset = (*arguments)[2];
5272 }
5273 if (offset != nullptr)
5274 {
5275 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
5276 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
5277 {
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005278 error(functionCall->getLine(), "Texture offset must be a constant expression",
Olli Etuahoec9232b2017-03-27 17:01:37 +03005279 name.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005280 }
5281 else
5282 {
5283 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
5284 size_t size = offsetConstantUnion->getType().getObjectSize();
5285 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
5286 for (size_t i = 0u; i < size; ++i)
5287 {
5288 int offsetValue = values[i].getIConst();
5289 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
5290 {
5291 std::stringstream tokenStream;
5292 tokenStream << offsetValue;
5293 std::string token = tokenStream.str();
5294 error(offset->getLine(), "Texture offset value out of valid range",
5295 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005296 }
5297 }
5298 }
5299 }
5300}
5301
Martin Radev2cc85b32016-08-05 16:22:53 +03005302// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
5303void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
5304{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08005305 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Martin Radev2cc85b32016-08-05 16:22:53 +03005306 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
5307
5308 if (name.compare(0, 5, "image") == 0)
5309 {
5310 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuaho485eefd2017-02-14 17:40:06 +00005311 TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
Martin Radev2cc85b32016-08-05 16:22:53 +03005312
Olli Etuaho485eefd2017-02-14 17:40:06 +00005313 const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
Martin Radev2cc85b32016-08-05 16:22:53 +03005314
5315 if (name.compare(5, 5, "Store") == 0)
5316 {
5317 if (memoryQualifier.readonly)
5318 {
5319 error(imageNode->getLine(),
5320 "'imageStore' cannot be used with images qualified as 'readonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005321 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03005322 }
5323 }
5324 else if (name.compare(5, 4, "Load") == 0)
5325 {
5326 if (memoryQualifier.writeonly)
5327 {
5328 error(imageNode->getLine(),
5329 "'imageLoad' cannot be used with images qualified as 'writeonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005330 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03005331 }
5332 }
5333 }
5334}
5335
5336// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
5337void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
5338 const TFunction *functionDefinition,
5339 const TIntermAggregate *functionCall)
5340{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08005341 ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
Martin Radev2cc85b32016-08-05 16:22:53 +03005342
5343 const TIntermSequence &arguments = *functionCall->getSequence();
5344
5345 ASSERT(functionDefinition->getParamCount() == arguments.size());
5346
5347 for (size_t i = 0; i < arguments.size(); ++i)
5348 {
Olli Etuaho485eefd2017-02-14 17:40:06 +00005349 TIntermTyped *typedArgument = arguments[i]->getAsTyped();
5350 const TType &functionArgumentType = typedArgument->getType();
Martin Radev2cc85b32016-08-05 16:22:53 +03005351 const TType &functionParameterType = *functionDefinition->getParam(i).type;
5352 ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
5353
5354 if (IsImage(functionArgumentType.getBasicType()))
5355 {
5356 const TMemoryQualifier &functionArgumentMemoryQualifier =
5357 functionArgumentType.getMemoryQualifier();
5358 const TMemoryQualifier &functionParameterMemoryQualifier =
5359 functionParameterType.getMemoryQualifier();
5360 if (functionArgumentMemoryQualifier.readonly &&
5361 !functionParameterMemoryQualifier.readonly)
5362 {
5363 error(functionCall->getLine(),
5364 "Function call discards the 'readonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005365 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03005366 }
5367
5368 if (functionArgumentMemoryQualifier.writeonly &&
5369 !functionParameterMemoryQualifier.writeonly)
5370 {
5371 error(functionCall->getLine(),
5372 "Function call discards the 'writeonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005373 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03005374 }
Martin Radev049edfa2016-11-11 14:35:37 +02005375
5376 if (functionArgumentMemoryQualifier.coherent &&
5377 !functionParameterMemoryQualifier.coherent)
5378 {
5379 error(functionCall->getLine(),
5380 "Function call discards the 'coherent' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005381 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02005382 }
5383
5384 if (functionArgumentMemoryQualifier.volatileQualifier &&
5385 !functionParameterMemoryQualifier.volatileQualifier)
5386 {
5387 error(functionCall->getLine(),
5388 "Function call discards the 'volatile' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005389 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02005390 }
Martin Radev2cc85b32016-08-05 16:22:53 +03005391 }
5392 }
5393}
5394
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005395TIntermSequence *TParseContext::createEmptyArgumentsList()
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005396{
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005397 return new TIntermSequence();
Olli Etuaho72d10202017-01-19 15:58:30 +00005398}
5399
5400TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005401 TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00005402 TIntermNode *thisNode,
5403 const TSourceLoc &loc)
5404{
Olli Etuahoffe6edf2015-04-13 17:32:03 +03005405 if (thisNode != nullptr)
5406 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005407 return addMethod(fnCall, arguments, thisNode, loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03005408 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005409
5410 TOperator op = fnCall->getBuiltInOp();
Olli Etuahoa7ecec32017-05-08 17:43:55 +03005411 if (op == EOpConstruct)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005412 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03005413 return addConstructor(arguments, fnCall->getReturnType(), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005414 }
5415 else
5416 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03005417 ASSERT(op == EOpNull);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005418 return addNonConstructorFunctionCall(fnCall, arguments, loc);
5419 }
5420}
5421
5422TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
5423 TIntermSequence *arguments,
5424 TIntermNode *thisNode,
5425 const TSourceLoc &loc)
5426{
5427 TConstantUnion *unionArray = new TConstantUnion[1];
5428 int arraySize = 0;
5429 TIntermTyped *typedThis = thisNode->getAsTyped();
5430 // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
5431 // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
5432 // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
5433 // So accessing fnCall->getName() below is safe.
5434 if (fnCall->getName() != "length")
5435 {
5436 error(loc, "invalid method", fnCall->getName().c_str());
5437 }
5438 else if (!arguments->empty())
5439 {
5440 error(loc, "method takes no parameters", "length");
5441 }
5442 else if (typedThis == nullptr || !typedThis->isArray())
5443 {
5444 error(loc, "length can only be called on arrays", "length");
5445 }
Jiawei Shaod8105a02017-08-08 09:54:36 +08005446 else if (typedThis->getQualifier() == EvqPerVertexIn &&
5447 mGeometryShaderInputPrimitiveType == EptUndefined)
5448 {
5449 error(loc, "missing input primitive declaration before calling length on gl_in", "length");
5450 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005451 else
5452 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03005453 arraySize = typedThis->getOutermostArraySize();
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005454 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuaho72d10202017-01-19 15:58:30 +00005455 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005456 // This code path can be hit with expressions like these:
5457 // (a = b).length()
5458 // (func()).length()
5459 // (int[3](0, 1, 2)).length()
5460 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
5461 // expression.
5462 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
5463 // spec section 5.9 which allows "An array, vector or matrix expression with the
5464 // length method applied".
5465 error(loc, "length can only be called on array names, not on array expressions",
5466 "length");
Olli Etuaho72d10202017-01-19 15:58:30 +00005467 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005468 }
5469 unionArray->setIConst(arraySize);
Olli Etuaho56229f12017-07-10 14:16:33 +03005470 TIntermConstantUnion *node =
5471 new TIntermConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst));
5472 node->setLine(loc);
5473 return node;
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005474}
5475
5476TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
5477 TIntermSequence *arguments,
5478 const TSourceLoc &loc)
5479{
5480 // First find by unmangled name to check whether the function name has been
5481 // hidden by a variable name or struct typename.
5482 // If a function is found, check for one with a matching argument list.
5483 bool builtIn;
5484 const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn);
5485 if (symbol != nullptr && !symbol->isFunction())
5486 {
5487 error(loc, "function name expected", fnCall->getName().c_str());
5488 }
5489 else
5490 {
5491 symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments),
5492 mShaderVersion, &builtIn);
5493 if (symbol == nullptr)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005494 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005495 error(loc, "no matching overloaded function found", fnCall->getName().c_str());
5496 }
5497 else
5498 {
5499 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005500 //
5501 // A declared function.
5502 //
Olli Etuaho383b7912016-08-05 11:22:59 +03005503 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005504 {
Olli Etuaho856c4972016-08-08 11:38:39 +03005505 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005506 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005507 TOperator op = fnCandidate->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005508 if (builtIn && op != EOpNull)
5509 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005510 // A function call mapped to a built-in operation.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005511 if (fnCandidate->getParamCount() == 1)
5512 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005513 // Treat it like a built-in unary operator.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005514 TIntermNode *unaryParamNode = arguments->front();
5515 TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08005516 ASSERT(callNode != nullptr);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005517 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005518 }
5519 else
5520 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005521 TIntermAggregate *callNode =
Olli Etuahofe486322017-03-21 09:30:54 +00005522 TIntermAggregate::Create(fnCandidate->getReturnType(), op, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005523 callNode->setLine(loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005524
5525 // Some built-in functions have out parameters too.
Jiajia Qinbc585152017-06-23 15:42:17 +08005526 functionCallRValueLValueErrorCheck(fnCandidate, callNode);
Arun Patole274f0702015-05-05 13:33:30 +05305527
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03005528 if (TIntermAggregate::CanFoldAggregateBuiltInOp(callNode->getOp()))
Arun Patole274f0702015-05-05 13:33:30 +05305529 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03005530 // See if we can constant fold a built-in. Note that this may be possible
5531 // even if it is not const-qualified.
5532 return callNode->fold(mDiagnostics);
Arun Patole274f0702015-05-05 13:33:30 +05305533 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03005534 else
5535 {
5536 return callNode;
5537 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005538 }
5539 }
5540 else
5541 {
5542 // This is a real function call
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005543 TIntermAggregate *callNode = nullptr;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005544
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08005545 // If builtIn == false, the function is user defined - could be an overloaded
5546 // built-in as well.
5547 // if builtIn == true, it's a builtIn function with no op associated with it.
5548 // This needs to happen after the function info including name is set.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005549 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005550 {
Olli Etuahofe486322017-03-21 09:30:54 +00005551 callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005552 checkTextureOffsetConst(callNode);
5553 checkImageMemoryAccessForBuiltinFunctions(callNode);
Martin Radev2cc85b32016-08-05 16:22:53 +03005554 }
5555 else
5556 {
Olli Etuahofe486322017-03-21 09:30:54 +00005557 callNode = TIntermAggregate::CreateFunctionCall(*fnCandidate, arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005558 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005559 }
5560
Jiajia Qinbc585152017-06-23 15:42:17 +08005561 functionCallRValueLValueErrorCheck(fnCandidate, callNode);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005562
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005563 callNode->setLine(loc);
5564
5565 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005566 }
5567 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005568 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005569
5570 // Error message was already written. Put on a dummy node for error recovery.
Olli Etuaho3ec75682017-07-05 17:02:55 +03005571 return CreateZeroNode(TType(EbtFloat, EbpMedium, EvqConst));
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005572}
5573
Jamie Madillb98c3a82015-07-23 14:26:04 -04005574TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005575 TIntermTyped *trueExpression,
5576 TIntermTyped *falseExpression,
Olli Etuaho52901742015-04-15 13:42:45 +03005577 const TSourceLoc &loc)
5578{
Olli Etuaho56229f12017-07-10 14:16:33 +03005579 if (!checkIsScalarBool(loc, cond))
5580 {
5581 return falseExpression;
5582 }
Olli Etuaho52901742015-04-15 13:42:45 +03005583
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005584 if (trueExpression->getType() != falseExpression->getType())
Olli Etuaho52901742015-04-15 13:42:45 +03005585 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03005586 std::stringstream reasonStream;
5587 reasonStream << "mismatching ternary operator operand types '"
5588 << trueExpression->getCompleteString() << " and '"
5589 << falseExpression->getCompleteString() << "'";
5590 std::string reason = reasonStream.str();
5591 error(loc, reason.c_str(), "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005592 return falseExpression;
Olli Etuaho52901742015-04-15 13:42:45 +03005593 }
Olli Etuahode318b22016-10-25 16:18:25 +01005594 if (IsOpaqueType(trueExpression->getBasicType()))
5595 {
5596 // ESSL 1.00 section 4.1.7
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005597 // ESSL 3.00.6 section 4.1.7
Olli Etuahode318b22016-10-25 16:18:25 +01005598 // Opaque/sampler types are not allowed in most types of expressions, including ternary.
5599 // Note that structs containing opaque types don't need to be checked as structs are
5600 // forbidden below.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005601 error(loc, "ternary operator is not allowed for opaque types", "?:");
Olli Etuahode318b22016-10-25 16:18:25 +01005602 return falseExpression;
5603 }
5604
Jiajia Qinbc585152017-06-23 15:42:17 +08005605 if (cond->getMemoryQualifier().writeonly || trueExpression->getMemoryQualifier().writeonly ||
5606 falseExpression->getMemoryQualifier().writeonly)
5607 {
5608 error(loc, "ternary operator is not allowed for variables with writeonly", "?:");
5609 return falseExpression;
5610 }
5611
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005612 // ESSL 1.00.17 sections 5.2 and 5.7:
Olli Etuahoa2d53032015-04-15 14:14:44 +03005613 // Ternary operator is not among the operators allowed for structures/arrays.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005614 // ESSL 3.00.6 section 5.7:
5615 // Ternary operator support is optional for arrays. No certainty that it works across all
5616 // devices with struct either, so we err on the side of caution here. TODO (oetuaho@nvidia.com):
5617 // Would be nice to make the spec and implementation agree completely here.
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005618 if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
Olli Etuahoa2d53032015-04-15 14:14:44 +03005619 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005620 error(loc, "ternary operator is not allowed for structures or arrays", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005621 return falseExpression;
Olli Etuahoa2d53032015-04-15 14:14:44 +03005622 }
Olli Etuaho94050052017-05-08 14:17:44 +03005623 if (trueExpression->getBasicType() == EbtInterfaceBlock)
5624 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005625 error(loc, "ternary operator is not allowed for interface blocks", "?:");
Olli Etuaho94050052017-05-08 14:17:44 +03005626 return falseExpression;
5627 }
5628
Corentin Wallez0d959252016-07-12 17:26:32 -04005629 // WebGL2 section 5.26, the following results in an error:
5630 // "Ternary operator applied to void, arrays, or structs containing arrays"
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005631 if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
Corentin Wallez0d959252016-07-12 17:26:32 -04005632 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005633 error(loc, "ternary operator is not allowed for void", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005634 return falseExpression;
Corentin Wallez0d959252016-07-12 17:26:32 -04005635 }
5636
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03005637 // Note that the node resulting from here can be a constant union without being qualified as
5638 // constant.
5639 TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression);
5640 node->setLine(loc);
5641
5642 return node->fold();
Olli Etuaho52901742015-04-15 13:42:45 +03005643}
Olli Etuaho49300862015-02-20 14:54:49 +02005644
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00005645//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00005646// Parse an array of strings using yyparse.
5647//
5648// Returns 0 for success.
5649//
Jamie Madillb98c3a82015-07-23 14:26:04 -04005650int PaParseStrings(size_t count,
5651 const char *const string[],
5652 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05305653 TParseContext *context)
5654{
Yunchao He4f285442017-04-21 12:15:49 +08005655 if ((count == 0) || (string == nullptr))
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00005656 return 1;
5657
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00005658 if (glslang_initialize(context))
5659 return 1;
5660
alokp@chromium.org408c45e2012-04-05 15:54:43 +00005661 int error = glslang_scan(count, string, length, context);
5662 if (!error)
5663 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00005664
alokp@chromium.org73bc2982012-06-19 18:48:05 +00005665 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00005666
alokp@chromium.org6b495712012-06-29 00:06:58 +00005667 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00005668}
Jamie Madill45bcc782016-11-07 13:58:48 -05005669
5670} // namespace sh