blob: 588488a884e8a95ed8ae5fffc1a3fc0284f3d542 [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"
Olli Etuahod5f44c92017-11-29 17:15:40 +020014#include "compiler/translator/Declarator.h"
Olli Etuaho2bfe9f62018-03-02 16:53:29 +020015#include "compiler/translator/ParseContext_autogen.h"
Kai Ninomiya614dd0f2017-11-22 14:04:48 -080016#include "compiler/translator/StaticType.h"
Olli Etuahob0c645e2015-05-12 14:25:36 +030017#include "compiler/translator/ValidateGlobalInitializer.h"
jchen104cdac9e2017-05-08 11:01:20 +080018#include "compiler/translator/ValidateSwitch.h"
19#include "compiler/translator/glslang.h"
Olli Etuahoc26214d2018-03-16 10:43:11 +020020#include "compiler/translator/tree_util/IntermNode_util.h"
Olli Etuaho37ad4742015-04-27 13:18:50 +030021#include "compiler/translator/util.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000022
Jamie Madill45bcc782016-11-07 13:58:48 -050023namespace sh
24{
25
alokp@chromium.org8b851c62012-06-15 16:25:11 +000026///////////////////////////////////////////////////////////////////////
27//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000028// Sub- vector and matrix fields
29//
30////////////////////////////////////////////////////////////////////////
31
Martin Radev2cc85b32016-08-05 16:22:53 +030032namespace
33{
34
35const int kWebGLMaxStructNesting = 4;
36
Olli Etuaho0f684632017-07-13 12:42:15 +030037bool ContainsSampler(const TStructure *structType);
38
Martin Radev2cc85b32016-08-05 16:22:53 +030039bool ContainsSampler(const TType &type)
40{
41 if (IsSampler(type.getBasicType()))
Olli Etuaho0f684632017-07-13 12:42:15 +030042 {
Martin Radev2cc85b32016-08-05 16:22:53 +030043 return true;
Olli Etuaho0f684632017-07-13 12:42:15 +030044 }
jchen10cc2a10e2017-05-03 14:05:12 +080045 if (type.getBasicType() == EbtStruct)
Martin Radev2cc85b32016-08-05 16:22:53 +030046 {
Olli Etuaho0f684632017-07-13 12:42:15 +030047 return ContainsSampler(type.getStruct());
Martin Radev2cc85b32016-08-05 16:22:53 +030048 }
49
50 return false;
51}
52
Olli Etuaho0f684632017-07-13 12:42:15 +030053bool ContainsSampler(const TStructure *structType)
54{
55 for (const auto &field : structType->fields())
56 {
57 if (ContainsSampler(*field->type()))
58 return true;
59 }
60 return false;
61}
62
Olli Etuaho485eefd2017-02-14 17:40:06 +000063// Get a token from an image argument to use as an error message token.
64const char *GetImageArgumentToken(TIntermTyped *imageNode)
65{
66 ASSERT(IsImage(imageNode->getBasicType()));
67 while (imageNode->getAsBinaryNode() &&
68 (imageNode->getAsBinaryNode()->getOp() == EOpIndexIndirect ||
69 imageNode->getAsBinaryNode()->getOp() == EOpIndexDirect))
70 {
71 imageNode = imageNode->getAsBinaryNode()->getLeft();
72 }
73 TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode();
74 if (imageSymbol)
75 {
Olli Etuahofbb1c792018-01-19 16:26:59 +020076 return imageSymbol->getName().data();
Olli Etuaho485eefd2017-02-14 17:40:06 +000077 }
78 return "image";
79}
80
Olli Etuahocce89652017-06-19 16:04:09 +030081bool CanSetDefaultPrecisionOnType(const TPublicType &type)
82{
83 if (!SupportsPrecision(type.getBasicType()))
84 {
85 return false;
86 }
87 if (type.getBasicType() == EbtUInt)
88 {
89 // ESSL 3.00.4 section 4.5.4
90 return false;
91 }
92 if (type.isAggregate())
93 {
94 // Not allowed to set for aggregate types
95 return false;
96 }
97 return true;
98}
99
Jiawei Shaod8105a02017-08-08 09:54:36 +0800100// Map input primitive types to input array sizes in a geometry shader.
101GLuint GetGeometryShaderInputArraySize(TLayoutPrimitiveType primitiveType)
102{
103 switch (primitiveType)
104 {
105 case EptPoints:
106 return 1u;
107 case EptLines:
108 return 2u;
109 case EptTriangles:
110 return 3u;
111 case EptLinesAdjacency:
112 return 4u;
113 case EptTrianglesAdjacency:
114 return 6u;
115 default:
116 UNREACHABLE();
117 return 0u;
118 }
119}
120
Jiajia Qina3106c52017-11-03 09:39:39 +0800121bool IsBufferOrSharedVariable(TIntermTyped *var)
122{
123 if (var->isInterfaceBlock() || var->getQualifier() == EvqBuffer ||
124 var->getQualifier() == EvqShared)
125 {
126 return true;
127 }
128 return false;
129}
130
Martin Radev2cc85b32016-08-05 16:22:53 +0300131} // namespace
132
jchen104cdac9e2017-05-08 11:01:20 +0800133// This tracks each binding point's current default offset for inheritance of subsequent
134// variables using the same binding, and keeps offsets unique and non overlapping.
135// See GLSL ES 3.1, section 4.4.6.
136class TParseContext::AtomicCounterBindingState
137{
138 public:
139 AtomicCounterBindingState() : mDefaultOffset(0) {}
140 // Inserts a new span and returns -1 if overlapping, else returns the starting offset of
141 // newly inserted span.
142 int insertSpan(int start, size_t length)
143 {
144 gl::RangeI newSpan(start, start + static_cast<int>(length));
145 for (const auto &span : mSpans)
146 {
147 if (newSpan.intersects(span))
148 {
149 return -1;
150 }
151 }
152 mSpans.push_back(newSpan);
153 mDefaultOffset = newSpan.high();
154 return start;
155 }
156 // Inserts a new span starting from the default offset.
157 int appendSpan(size_t length) { return insertSpan(mDefaultOffset, length); }
158 void setDefaultOffset(int offset) { mDefaultOffset = offset; }
159
160 private:
161 int mDefaultOffset;
162 std::vector<gl::RangeI> mSpans;
163};
164
Jamie Madillacb4b812016-11-07 13:50:29 -0500165TParseContext::TParseContext(TSymbolTable &symt,
166 TExtensionBehavior &ext,
167 sh::GLenum type,
168 ShShaderSpec spec,
Jamie Madillacb4b812016-11-07 13:50:29 -0500169 bool checksPrecErrors,
Olli Etuaho77ba4082016-12-16 12:01:18 +0000170 TDiagnostics *diagnostics,
Jamie Madillacb4b812016-11-07 13:50:29 -0500171 const ShBuiltInResources &resources)
Olli Etuaho56229f12017-07-10 14:16:33 +0300172 : symbolTable(symt),
Olli Etuahobb7e5a72017-04-24 10:16:44 +0300173 mDeferredNonEmptyDeclarationErrorCheck(false),
Jamie Madillacb4b812016-11-07 13:50:29 -0500174 mShaderType(type),
175 mShaderSpec(spec),
Jamie Madillacb4b812016-11-07 13:50:29 -0500176 mShaderVersion(100),
177 mTreeRoot(nullptr),
178 mLoopNestingLevel(0),
179 mStructNestingLevel(0),
180 mSwitchNestingLevel(0),
181 mCurrentFunctionType(nullptr),
182 mFunctionReturnsValue(false),
183 mChecksPrecisionErrors(checksPrecErrors),
184 mFragmentPrecisionHighOnESSL1(false),
Jiajia Qinbc585152017-06-23 15:42:17 +0800185 mDefaultUniformMatrixPacking(EmpColumnMajor),
186 mDefaultUniformBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
187 mDefaultBufferMatrixPacking(EmpColumnMajor),
188 mDefaultBufferBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
Olli Etuaho77ba4082016-12-16 12:01:18 +0000189 mDiagnostics(diagnostics),
Jamie Madillacb4b812016-11-07 13:50:29 -0500190 mDirectiveHandler(ext,
Olli Etuaho77ba4082016-12-16 12:01:18 +0000191 *mDiagnostics,
Jamie Madillacb4b812016-11-07 13:50:29 -0500192 mShaderVersion,
193 mShaderType,
194 resources.WEBGL_debug_shader_precision == 1),
Jamie Madillc3bef3e2018-10-03 07:35:09 -0400195 mPreprocessor(mDiagnostics, &mDirectiveHandler, angle::pp::PreprocessorSettings(spec)),
Jamie Madillacb4b812016-11-07 13:50:29 -0500196 mScanner(nullptr),
Jamie Madillacb4b812016-11-07 13:50:29 -0500197 mMinProgramTexelOffset(resources.MinProgramTexelOffset),
198 mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
Martin Radev84aa2dc2017-09-11 15:51:02 +0300199 mMinProgramTextureGatherOffset(resources.MinProgramTextureGatherOffset),
200 mMaxProgramTextureGatherOffset(resources.MaxProgramTextureGatherOffset),
Jamie Madillacb4b812016-11-07 13:50:29 -0500201 mComputeShaderLocalSizeDeclared(false),
Jamie Madill2f294c92017-11-20 14:47:26 -0500202 mComputeShaderLocalSize(-1),
Olli Etuaho09b04a22016-12-15 13:30:26 +0000203 mNumViews(-1),
204 mMaxNumViews(resources.MaxViewsOVR),
Olli Etuaho43364892017-02-13 16:00:12 +0000205 mMaxImageUnits(resources.MaxImageUnits),
206 mMaxCombinedTextureImageUnits(resources.MaxCombinedTextureImageUnits),
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000207 mMaxUniformLocations(resources.MaxUniformLocations),
jchen10af713a22017-04-19 09:10:56 +0800208 mMaxUniformBufferBindings(resources.MaxUniformBufferBindings),
jchen104cdac9e2017-05-08 11:01:20 +0800209 mMaxAtomicCounterBindings(resources.MaxAtomicCounterBindings),
Jiajia Qinbc585152017-06-23 15:42:17 +0800210 mMaxShaderStorageBufferBindings(resources.MaxShaderStorageBufferBindings),
Shaob5cc1192017-07-06 10:47:20 +0800211 mDeclaringFunction(false),
212 mGeometryShaderInputPrimitiveType(EptUndefined),
213 mGeometryShaderOutputPrimitiveType(EptUndefined),
214 mGeometryShaderInvocations(0),
215 mGeometryShaderMaxVertices(-1),
216 mMaxGeometryShaderInvocations(resources.MaxGeometryShaderInvocations),
Olli Etuaho94bbed12018-03-20 14:44:53 +0200217 mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices)
Jamie Madillb980c562018-11-27 11:34:27 -0500218{}
Jamie Madillacb4b812016-11-07 13:50:29 -0500219
Jamie Madillb980c562018-11-27 11:34:27 -0500220TParseContext::~TParseContext() {}
jchen104cdac9e2017-05-08 11:01:20 +0800221
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300222bool TParseContext::parseVectorFields(const TSourceLoc &line,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200223 const ImmutableString &compString,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400224 int vecSize,
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300225 TVector<int> *fieldOffsets)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000226{
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300227 ASSERT(fieldOffsets);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200228 size_t fieldCount = compString.length();
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300229 if (fieldCount > 4u)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530230 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200231 error(line, "illegal vector field selection", compString);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000232 return false;
233 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300234 fieldOffsets->resize(fieldCount);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000235
Jamie Madillb98c3a82015-07-23 14:26:04 -0400236 enum
237 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000238 exyzw,
239 ergba,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000240 estpq
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000241 } fieldSet[4];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300243 for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530244 {
245 switch (compString[i])
246 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400247 case 'x':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300248 (*fieldOffsets)[i] = 0;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400249 fieldSet[i] = exyzw;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400250 break;
251 case 'r':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300252 (*fieldOffsets)[i] = 0;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400253 fieldSet[i] = ergba;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400254 break;
255 case 's':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300256 (*fieldOffsets)[i] = 0;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400257 fieldSet[i] = estpq;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400258 break;
259 case 'y':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300260 (*fieldOffsets)[i] = 1;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400261 fieldSet[i] = exyzw;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400262 break;
263 case 'g':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300264 (*fieldOffsets)[i] = 1;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400265 fieldSet[i] = ergba;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400266 break;
267 case 't':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300268 (*fieldOffsets)[i] = 1;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400269 fieldSet[i] = estpq;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400270 break;
271 case 'z':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300272 (*fieldOffsets)[i] = 2;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400273 fieldSet[i] = exyzw;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400274 break;
275 case 'b':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300276 (*fieldOffsets)[i] = 2;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400277 fieldSet[i] = ergba;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400278 break;
279 case 'p':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300280 (*fieldOffsets)[i] = 2;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400281 fieldSet[i] = estpq;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400282 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530283
Jamie Madillb98c3a82015-07-23 14:26:04 -0400284 case 'w':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300285 (*fieldOffsets)[i] = 3;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400286 fieldSet[i] = exyzw;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400287 break;
288 case 'a':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300289 (*fieldOffsets)[i] = 3;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400290 fieldSet[i] = ergba;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400291 break;
292 case 'q':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300293 (*fieldOffsets)[i] = 3;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400294 fieldSet[i] = estpq;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400295 break;
296 default:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200297 error(line, "illegal vector field selection", compString);
Jamie Madillb98c3a82015-07-23 14:26:04 -0400298 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000299 }
300 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000301
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300302 for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530303 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300304 if ((*fieldOffsets)[i] >= vecSize)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530305 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200306 error(line, "vector field selection out of range", compString);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000307 return false;
308 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000309
Arun Patole7e7e68d2015-05-22 12:02:25 +0530310 if (i > 0)
311 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400312 if (fieldSet[i] != fieldSet[i - 1])
Arun Patole7e7e68d2015-05-22 12:02:25 +0530313 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200314 error(line, "illegal - vector component fields not from the same set", compString);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000315 return false;
316 }
317 }
318 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000319
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000320 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000321}
322
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000323///////////////////////////////////////////////////////////////////////
324//
325// Errors
326//
327////////////////////////////////////////////////////////////////////////
328
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000329//
330// Used by flex/bison to output all syntax and parsing errors.
331//
Olli Etuaho4de340a2016-12-16 09:32:03 +0000332void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000333{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000334 mDiagnostics->error(loc, reason, token);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000335}
336
Olli Etuahofbb1c792018-01-19 16:26:59 +0200337void TParseContext::error(const TSourceLoc &loc, const char *reason, const ImmutableString &token)
338{
339 mDiagnostics->error(loc, reason, token.data());
340}
341
Olli Etuaho4de340a2016-12-16 09:32:03 +0000342void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530343{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000344 mDiagnostics->warning(loc, reason, token);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +0000345}
346
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200347void TParseContext::outOfRangeError(bool isError,
348 const TSourceLoc &loc,
349 const char *reason,
Olli Etuaho4de340a2016-12-16 09:32:03 +0000350 const char *token)
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200351{
352 if (isError)
353 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000354 error(loc, reason, token);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200355 }
356 else
357 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000358 warning(loc, reason, token);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200359 }
360}
361
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000362//
363// Same error message for all places assignments don't work.
364//
Olli Etuaho72e35892018-06-20 11:43:08 +0300365void TParseContext::assignError(const TSourceLoc &line,
366 const char *op,
367 const TType &left,
368 const TType &right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000369{
Olli Etuaho72e35892018-06-20 11:43:08 +0300370 TInfoSinkBase reasonStream;
Olli Etuaho4de340a2016-12-16 09:32:03 +0000371 reasonStream << "cannot convert from '" << right << "' to '" << left << "'";
Olli Etuaho72e35892018-06-20 11:43:08 +0300372 error(line, reasonStream.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000373}
374
375//
376// Same error message for all places unary operations don't work.
377//
Olli Etuaho72e35892018-06-20 11:43:08 +0300378void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, const TType &operand)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000379{
Olli Etuaho72e35892018-06-20 11:43:08 +0300380 TInfoSinkBase reasonStream;
Olli Etuaho4de340a2016-12-16 09:32:03 +0000381 reasonStream << "wrong operand type - no operation '" << op
382 << "' exists that takes an operand of type " << operand
383 << " (or there is no acceptable conversion)";
Olli Etuaho72e35892018-06-20 11:43:08 +0300384 error(line, reasonStream.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000385}
386
387//
388// Same error message for all binary operations don't work.
389//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400390void TParseContext::binaryOpError(const TSourceLoc &line,
391 const char *op,
Olli Etuaho72e35892018-06-20 11:43:08 +0300392 const TType &left,
393 const TType &right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000394{
Olli Etuaho72e35892018-06-20 11:43:08 +0300395 TInfoSinkBase reasonStream;
Olli Etuaho4de340a2016-12-16 09:32:03 +0000396 reasonStream << "wrong operand types - no operation '" << op
397 << "' exists that takes a left-hand operand of type '" << left
398 << "' and a right operand of type '" << right
399 << "' (or there is no acceptable conversion)";
Olli Etuaho72e35892018-06-20 11:43:08 +0300400 error(line, reasonStream.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000401}
402
Olli Etuaho856c4972016-08-08 11:38:39 +0300403void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
404 TPrecision precision,
405 TBasicType type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530406{
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400407 if (!mChecksPrecisionErrors)
Olli Etuaho383b7912016-08-05 11:22:59 +0300408 return;
Martin Radev70866b82016-07-22 15:27:42 +0300409
410 if (precision != EbpUndefined && !SupportsPrecision(type))
411 {
412 error(line, "illegal type for precision qualifier", getBasicString(type));
413 }
414
Olli Etuaho183d7e22015-11-20 15:59:09 +0200415 if (precision == EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530416 {
Olli Etuaho183d7e22015-11-20 15:59:09 +0200417 switch (type)
418 {
419 case EbtFloat:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400420 error(line, "No precision specified for (float)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300421 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200422 case EbtInt:
423 case EbtUInt:
424 UNREACHABLE(); // there's always a predeclared qualifier
Jamie Madillb98c3a82015-07-23 14:26:04 -0400425 error(line, "No precision specified (int)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300426 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200427 default:
jchen10cc2a10e2017-05-03 14:05:12 +0800428 if (IsOpaqueType(type))
Olli Etuaho183d7e22015-11-20 15:59:09 +0200429 {
jchen10cc2a10e2017-05-03 14:05:12 +0800430 error(line, "No precision specified", getBasicString(type));
Martin Radev2cc85b32016-08-05 16:22:53 +0300431 return;
432 }
Olli Etuaho183d7e22015-11-20 15:59:09 +0200433 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000434 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000435}
436
Olli Etuaho94bbed12018-03-20 14:44:53 +0200437void TParseContext::markStaticReadIfSymbol(TIntermNode *node)
438{
439 TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
440 if (swizzleNode)
441 {
442 markStaticReadIfSymbol(swizzleNode->getOperand());
443 return;
444 }
445 TIntermBinary *binaryNode = node->getAsBinaryNode();
446 if (binaryNode)
447 {
448 switch (binaryNode->getOp())
449 {
450 case EOpIndexDirect:
451 case EOpIndexIndirect:
452 case EOpIndexDirectStruct:
453 case EOpIndexDirectInterfaceBlock:
454 markStaticReadIfSymbol(binaryNode->getLeft());
455 return;
456 default:
457 return;
458 }
459 }
460 TIntermSymbol *symbolNode = node->getAsSymbolNode();
461 if (symbolNode)
462 {
463 symbolTable.markStaticRead(symbolNode->variable());
464 }
465}
466
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000467// Both test and if necessary, spit out an error, to see if the node is really
468// an l-value that can be operated on this way.
Olli Etuaho856c4972016-08-08 11:38:39 +0300469bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000470{
Olli Etuahob6fa0432016-09-28 16:28:05 +0100471 TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
Olli Etuahob6fa0432016-09-28 16:28:05 +0100472 if (swizzleNode)
473 {
474 bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
475 if (ok && swizzleNode->hasDuplicateOffsets())
476 {
477 error(line, " l-value of swizzle cannot have duplicate components", op);
478 return false;
479 }
480 return ok;
481 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000482
Olli Etuahodaf120b2018-03-20 14:21:10 +0200483 TIntermBinary *binaryNode = node->getAsBinaryNode();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530484 if (binaryNode)
485 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400486 switch (binaryNode->getOp())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530487 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400488 case EOpIndexDirect:
489 case EOpIndexIndirect:
490 case EOpIndexDirectStruct:
491 case EOpIndexDirectInterfaceBlock:
Qin Jiajia76bf01d2018-02-22 14:11:34 +0800492 if (node->getMemoryQualifier().readonly)
493 {
494 error(line, "can't modify a readonly variable", op);
495 return false;
496 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300497 return checkCanBeLValue(line, op, binaryNode->getLeft());
Jamie Madillb98c3a82015-07-23 14:26:04 -0400498 default:
499 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000500 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000501 error(line, " l-value required", op);
Olli Etuaho8a176262016-08-16 14:23:01 +0300502 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000503 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000504
jchen10cc2a10e2017-05-03 14:05:12 +0800505 std::string message;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530506 switch (node->getQualifier())
507 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400508 case EvqConst:
509 message = "can't modify a const";
510 break;
511 case EvqConstReadOnly:
512 message = "can't modify a const";
513 break;
514 case EvqAttribute:
515 message = "can't modify an attribute";
516 break;
517 case EvqFragmentIn:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400518 case EvqVertexIn:
Jiawei Shao8e4b3552017-08-30 14:20:58 +0800519 case EvqGeometryIn:
Jiawei Shaoe8ef2bc2017-08-29 13:38:57 +0800520 case EvqFlatIn:
521 case EvqSmoothIn:
522 case EvqCentroidIn:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400523 message = "can't modify an input";
524 break;
525 case EvqUniform:
526 message = "can't modify a uniform";
527 break;
528 case EvqVaryingIn:
529 message = "can't modify a varying";
530 break;
531 case EvqFragCoord:
532 message = "can't modify gl_FragCoord";
533 break;
534 case EvqFrontFacing:
535 message = "can't modify gl_FrontFacing";
536 break;
537 case EvqPointCoord:
538 message = "can't modify gl_PointCoord";
539 break;
Martin Radevb0883602016-08-04 17:48:58 +0300540 case EvqNumWorkGroups:
541 message = "can't modify gl_NumWorkGroups";
542 break;
543 case EvqWorkGroupSize:
544 message = "can't modify gl_WorkGroupSize";
545 break;
546 case EvqWorkGroupID:
547 message = "can't modify gl_WorkGroupID";
548 break;
549 case EvqLocalInvocationID:
550 message = "can't modify gl_LocalInvocationID";
551 break;
552 case EvqGlobalInvocationID:
553 message = "can't modify gl_GlobalInvocationID";
554 break;
555 case EvqLocalInvocationIndex:
556 message = "can't modify gl_LocalInvocationIndex";
557 break;
Olli Etuaho7142f6c2017-05-05 17:07:26 +0300558 case EvqViewIDOVR:
559 message = "can't modify gl_ViewID_OVR";
560 break;
Martin Radev802abe02016-08-04 17:48:32 +0300561 case EvqComputeIn:
562 message = "can't modify work group size variable";
563 break;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800564 case EvqPerVertexIn:
565 message = "can't modify any member in gl_in";
566 break;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800567 case EvqPrimitiveIDIn:
568 message = "can't modify gl_PrimitiveIDIn";
569 break;
570 case EvqInvocationID:
571 message = "can't modify gl_InvocationID";
572 break;
573 case EvqPrimitiveID:
574 if (mShaderType == GL_FRAGMENT_SHADER)
575 {
576 message = "can't modify gl_PrimitiveID in a fragment shader";
577 }
578 break;
579 case EvqLayer:
580 if (mShaderType == GL_FRAGMENT_SHADER)
581 {
582 message = "can't modify gl_Layer in a fragment shader";
583 }
584 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400585 default:
586 //
587 // Type that can't be written to?
588 //
589 if (node->getBasicType() == EbtVoid)
590 {
591 message = "can't modify void";
592 }
jchen10cc2a10e2017-05-03 14:05:12 +0800593 if (IsOpaqueType(node->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -0400594 {
jchen10cc2a10e2017-05-03 14:05:12 +0800595 message = "can't modify a variable with type ";
596 message += getBasicString(node->getBasicType());
Martin Radev2cc85b32016-08-05 16:22:53 +0300597 }
Jiajia Qinbc585152017-06-23 15:42:17 +0800598 else if (node->getMemoryQualifier().readonly)
599 {
600 message = "can't modify a readonly variable";
601 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000602 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000603
Olli Etuahodaf120b2018-03-20 14:21:10 +0200604 ASSERT(binaryNode == nullptr && swizzleNode == nullptr);
605 TIntermSymbol *symNode = node->getAsSymbolNode();
606 if (message.empty() && symNode != nullptr)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530607 {
Olli Etuaho94bbed12018-03-20 14:44:53 +0200608 symbolTable.markStaticWrite(symNode->variable());
Olli Etuaho8a176262016-08-16 14:23:01 +0300609 return true;
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000610 }
Olli Etuahodaf120b2018-03-20 14:21:10 +0200611
Jonah Ryan-Davisf563fdc2019-01-31 13:53:59 -0500612 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
Olli Etuahodaf120b2018-03-20 14:21:10 +0200613 reasonStream << "l-value required";
614 if (!message.empty())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530615 {
Olli Etuahodaf120b2018-03-20 14:21:10 +0200616 if (symNode)
617 {
618 // Symbol inside an expression can't be nameless.
619 ASSERT(symNode->variable().symbolType() != SymbolType::Empty);
620 const ImmutableString &symbol = symNode->getName();
621 reasonStream << " (" << message << " \"" << symbol << "\")";
622 }
623 else
624 {
625 reasonStream << " (" << message << ")";
626 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000627 }
Olli Etuahodaf120b2018-03-20 14:21:10 +0200628 std::string reason = reasonStream.str();
629 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000630
Olli Etuaho8a176262016-08-16 14:23:01 +0300631 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000632}
633
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000634// Both test, and if necessary spit out an error, to see if the node is really
635// a constant.
Olli Etuaho856c4972016-08-08 11:38:39 +0300636void TParseContext::checkIsConst(TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000637{
Olli Etuaho383b7912016-08-05 11:22:59 +0300638 if (node->getQualifier() != EvqConst)
639 {
640 error(node->getLine(), "constant expression required", "");
641 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000642}
643
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000644// Both test, and if necessary spit out an error, to see if the node is really
645// an integer.
Olli Etuaho856c4972016-08-08 11:38:39 +0300646void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000647{
Olli Etuaho383b7912016-08-05 11:22:59 +0300648 if (!node->isScalarInt())
649 {
650 error(node->getLine(), "integer expression required", token);
651 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000652}
653
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000654// Both test, and if necessary spit out an error, to see if we are currently
655// globally scoped.
Qiankun Miaof69682b2016-08-16 14:50:42 +0800656bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000657{
Olli Etuaho856c4972016-08-08 11:38:39 +0300658 if (!symbolTable.atGlobalLevel())
Olli Etuaho383b7912016-08-05 11:22:59 +0300659 {
660 error(line, "only allowed at global scope", token);
Qiankun Miaof69682b2016-08-16 14:50:42 +0800661 return false;
Olli Etuaho383b7912016-08-05 11:22:59 +0300662 }
Qiankun Miaof69682b2016-08-16 14:50:42 +0800663 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000664}
665
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300666// ESSL 3.00.5 sections 3.8 and 3.9.
667// If it starts "gl_" or contains two consecutive underscores, it's reserved.
668// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a webgl shader.
Olli Etuahofbb1c792018-01-19 16:26:59 +0200669bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const ImmutableString &identifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000670{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530671 static const char *reservedErrMsg = "reserved built-in name";
Olli Etuahofbb1c792018-01-19 16:26:59 +0200672 if (identifier.beginsWith("gl_"))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530673 {
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300674 error(line, reservedErrMsg, "gl_");
675 return false;
676 }
677 if (sh::IsWebGLBasedSpec(mShaderSpec))
678 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200679 if (identifier.beginsWith("webgl_"))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530680 {
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300681 error(line, reservedErrMsg, "webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300682 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000683 }
Olli Etuahofbb1c792018-01-19 16:26:59 +0200684 if (identifier.beginsWith("_webgl_"))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530685 {
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300686 error(line, reservedErrMsg, "_webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300687 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000688 }
689 }
Olli Etuahofbb1c792018-01-19 16:26:59 +0200690 if (identifier.contains("__"))
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300691 {
692 error(line,
693 "identifiers containing two consecutive underscores (__) are reserved as "
694 "possible future keywords",
Olli Etuahofbb1c792018-01-19 16:26:59 +0200695 identifier);
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300696 return false;
697 }
Olli Etuaho8a176262016-08-16 14:23:01 +0300698 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000699}
700
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300701// Make sure the argument types are correct for constructing a specific type.
Olli Etuaho856c4972016-08-08 11:38:39 +0300702bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
Olli Etuaho95ed1942018-02-01 14:01:19 +0200703 const TIntermSequence &arguments,
Olli Etuaho856c4972016-08-08 11:38:39 +0300704 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000705{
Olli Etuaho95ed1942018-02-01 14:01:19 +0200706 if (arguments.empty())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530707 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200708 error(line, "constructor does not have any arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300709 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000710 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200711
Olli Etuaho95ed1942018-02-01 14:01:19 +0200712 for (TIntermNode *arg : arguments)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530713 {
Olli Etuaho94bbed12018-03-20 14:44:53 +0200714 markStaticReadIfSymbol(arg);
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300715 const TIntermTyped *argTyped = arg->getAsTyped();
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200716 ASSERT(argTyped != nullptr);
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300717 if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType()))
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200718 {
jchen10cc2a10e2017-05-03 14:05:12 +0800719 std::string reason("cannot convert a variable with type ");
720 reason += getBasicString(argTyped->getBasicType());
721 error(line, reason.c_str(), "constructor");
Martin Radev2cc85b32016-08-05 16:22:53 +0300722 return false;
723 }
Jiajia Qinbc585152017-06-23 15:42:17 +0800724 else if (argTyped->getMemoryQualifier().writeonly)
725 {
726 error(line, "cannot convert a variable with writeonly", "constructor");
727 return false;
728 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200729 if (argTyped->getBasicType() == EbtVoid)
730 {
731 error(line, "cannot convert a void", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300732 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200733 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000734 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000735
Olli Etuaho856c4972016-08-08 11:38:39 +0300736 if (type.isArray())
737 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300738 // The size of an unsized constructor should already have been determined.
739 ASSERT(!type.isUnsizedArray());
Olli Etuaho95ed1942018-02-01 14:01:19 +0200740 if (static_cast<size_t>(type.getOutermostArraySize()) != arguments.size())
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300741 {
742 error(line, "array constructor needs one argument per array element", "constructor");
743 return false;
744 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300745 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
746 // the array.
Olli Etuaho95ed1942018-02-01 14:01:19 +0200747 for (TIntermNode *const &argNode : arguments)
Olli Etuaho856c4972016-08-08 11:38:39 +0300748 {
749 const TType &argType = argNode->getAsTyped()->getType();
Olli Etuaho7881cfd2017-08-23 18:00:21 +0300750 if (mShaderVersion < 310 && argType.isArray())
Jamie Madill34bf2d92017-02-06 13:40:59 -0500751 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300752 error(line, "constructing from a non-dereferenced array", "constructor");
Jamie Madill34bf2d92017-02-06 13:40:59 -0500753 return false;
754 }
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300755 if (!argType.isElementTypeOf(type))
Olli Etuaho856c4972016-08-08 11:38:39 +0300756 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000757 error(line, "Array constructor argument has an incorrect type", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300758 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300759 }
760 }
761 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300762 else if (type.getBasicType() == EbtStruct)
Olli Etuaho856c4972016-08-08 11:38:39 +0300763 {
764 const TFieldList &fields = type.getStruct()->fields();
Olli Etuaho95ed1942018-02-01 14:01:19 +0200765 if (fields.size() != arguments.size())
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300766 {
767 error(line,
768 "Number of constructor parameters does not match the number of structure fields",
769 "constructor");
770 return false;
771 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300772
773 for (size_t i = 0; i < fields.size(); i++)
774 {
Olli Etuaho95ed1942018-02-01 14:01:19 +0200775 if (i >= arguments.size() ||
776 arguments[i]->getAsTyped()->getType() != *fields[i]->type())
Olli Etuaho856c4972016-08-08 11:38:39 +0300777 {
778 error(line, "Structure constructor arguments do not match structure fields",
Olli Etuaho4de340a2016-12-16 09:32:03 +0000779 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300780 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300781 }
782 }
783 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300784 else
785 {
786 // We're constructing a scalar, vector, or matrix.
787
788 // Note: It's okay to have too many components available, but not okay to have unused
789 // arguments. 'full' will go to true when enough args have been seen. If we loop again,
790 // there is an extra argument, so 'overFull' will become true.
791
792 size_t size = 0;
793 bool full = false;
794 bool overFull = false;
795 bool matrixArg = false;
Olli Etuaho95ed1942018-02-01 14:01:19 +0200796 for (TIntermNode *arg : arguments)
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300797 {
798 const TIntermTyped *argTyped = arg->getAsTyped();
799 ASSERT(argTyped != nullptr);
800
Olli Etuaho487b63a2017-05-23 15:55:09 +0300801 if (argTyped->getBasicType() == EbtStruct)
802 {
803 error(line, "a struct cannot be used as a constructor argument for this type",
804 "constructor");
805 return false;
806 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300807 if (argTyped->getType().isArray())
808 {
809 error(line, "constructing from a non-dereferenced array", "constructor");
810 return false;
811 }
812 if (argTyped->getType().isMatrix())
813 {
814 matrixArg = true;
815 }
816
817 size += argTyped->getType().getObjectSize();
818 if (full)
819 {
820 overFull = true;
821 }
Olli Etuaho487b63a2017-05-23 15:55:09 +0300822 if (size >= type.getObjectSize())
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300823 {
824 full = true;
825 }
826 }
827
828 if (type.isMatrix() && matrixArg)
829 {
Olli Etuaho95ed1942018-02-01 14:01:19 +0200830 if (arguments.size() != 1)
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300831 {
832 error(line, "constructing matrix from matrix can only take one argument",
833 "constructor");
834 return false;
835 }
836 }
837 else
838 {
839 if (size != 1 && size < type.getObjectSize())
840 {
841 error(line, "not enough data provided for construction", "constructor");
842 return false;
843 }
844 if (overFull)
845 {
846 error(line, "too many arguments", "constructor");
847 return false;
848 }
849 }
850 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300851
Olli Etuaho8a176262016-08-16 14:23:01 +0300852 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000853}
854
Jamie Madillb98c3a82015-07-23 14:26:04 -0400855// This function checks to see if a void variable has been declared and raise an error message for
856// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000857//
858// returns true in case of an error
859//
Olli Etuaho856c4972016-08-08 11:38:39 +0300860bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200861 const ImmutableString &identifier,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400862 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000863{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300864 if (type == EbtVoid)
865 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200866 error(line, "illegal use of type 'void'", identifier);
Olli Etuaho8a176262016-08-16 14:23:01 +0300867 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300868 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000869
Olli Etuaho8a176262016-08-16 14:23:01 +0300870 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000871}
872
Jamie Madillb98c3a82015-07-23 14:26:04 -0400873// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300874// or not.
Olli Etuaho56229f12017-07-10 14:16:33 +0300875bool TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000876{
Olli Etuaho37d96cc2017-07-11 14:14:03 +0300877 if (type->getBasicType() != EbtBool || !type->isScalar())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530878 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000879 error(line, "boolean expression expected", "");
Olli Etuaho56229f12017-07-10 14:16:33 +0300880 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530881 }
Olli Etuaho56229f12017-07-10 14:16:33 +0300882 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000883}
884
Jamie Madillb98c3a82015-07-23 14:26:04 -0400885// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300886// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300887void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000888{
Martin Radev4a9cd802016-09-01 16:51:51 +0300889 if (pType.getBasicType() != EbtBool || pType.isAggregate())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530890 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000891 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530892 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000893}
894
jchen10cc2a10e2017-05-03 14:05:12 +0800895bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
896 const TTypeSpecifierNonArray &pType,
897 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000898{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530899 if (pType.type == EbtStruct)
900 {
Olli Etuaho0f684632017-07-13 12:42:15 +0300901 if (ContainsSampler(pType.userDef))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530902 {
Jonah Ryan-Davisf563fdc2019-01-31 13:53:59 -0500903 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
Olli Etuaho4de340a2016-12-16 09:32:03 +0000904 reasonStream << reason << " (structure contains a sampler)";
905 std::string reasonStr = reasonStream.str();
906 error(line, reasonStr.c_str(), getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300907 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000908 }
jchen10cc2a10e2017-05-03 14:05:12 +0800909 // only samplers need to be checked from structs, since other opaque types can't be struct
910 // members.
Olli Etuaho8a176262016-08-16 14:23:01 +0300911 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530912 }
jchen10cc2a10e2017-05-03 14:05:12 +0800913 else if (IsOpaqueType(pType.type))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530914 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000915 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300916 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000917 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000918
Olli Etuaho8a176262016-08-16 14:23:01 +0300919 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000920}
921
Olli Etuaho856c4972016-08-08 11:38:39 +0300922void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
923 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400924{
925 if (pType.layoutQualifier.location != -1)
926 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400927 error(line, "location must only be specified for a single input or output variable",
928 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400929 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400930}
931
Olli Etuaho856c4972016-08-08 11:38:39 +0300932void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
933 const TLayoutQualifier &layoutQualifier)
934{
935 if (layoutQualifier.location != -1)
936 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000937 const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs";
938 if (mShaderVersion >= 310)
939 {
940 errorMsg =
Jiawei Shao4cc89e22017-08-31 14:25:54 +0800941 "invalid layout qualifier: only valid on shader inputs, outputs, and uniforms";
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000942 }
943 error(location, errorMsg, "location");
Olli Etuaho856c4972016-08-08 11:38:39 +0300944 }
945}
946
Qin Jiajiaca68d982017-09-18 16:41:56 +0800947void TParseContext::checkStd430IsForShaderStorageBlock(const TSourceLoc &location,
948 const TLayoutBlockStorage &blockStorage,
949 const TQualifier &qualifier)
950{
951 if (blockStorage == EbsStd430 && qualifier != EvqBuffer)
952 {
953 error(location, "The std430 layout is supported only for shader storage blocks.", "std430");
954 }
955}
956
Martin Radev2cc85b32016-08-05 16:22:53 +0300957void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
958 TQualifier qualifier,
959 const TType &type)
960{
Martin Radev2cc85b32016-08-05 16:22:53 +0300961 ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
jchen10cc2a10e2017-05-03 14:05:12 +0800962 if (IsOpaqueType(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530963 {
jchen10cc2a10e2017-05-03 14:05:12 +0800964 error(line, "opaque types cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000965 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000966}
967
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000968// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300969unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000970{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530971 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000972
Olli Etuaho1dfd8ae2018-10-01 15:59:59 +0300973 // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be
974 // safe against corner cases we still check for constant folding. Some interpretations of the
975 // spec have allowed constant expressions with side effects - like array length() method on a
976 // non-constant array.
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200977 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000978 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000979 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300980 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000981 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000982
Olli Etuaho856c4972016-08-08 11:38:39 +0300983 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400984
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000985 if (constant->getBasicType() == EbtUInt)
986 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300987 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000988 }
989 else
990 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300991 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000992
Olli Etuaho856c4972016-08-08 11:38:39 +0300993 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000994 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400995 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300996 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000997 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400998
Olli Etuaho856c4972016-08-08 11:38:39 +0300999 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -04001000 }
1001
Olli Etuaho856c4972016-08-08 11:38:39 +03001002 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -04001003 {
1004 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +03001005 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -04001006 }
1007
1008 // The size of arrays is restricted here to prevent issues further down the
1009 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
1010 // 4096 registers so this should be reasonable even for aggressively optimizable code.
1011 const unsigned int sizeLimit = 65536;
1012
Olli Etuaho856c4972016-08-08 11:38:39 +03001013 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -04001014 {
1015 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +03001016 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001017 }
Olli Etuaho856c4972016-08-08 11:38:39 +03001018
1019 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001020}
1021
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001022// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +03001023bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
1024 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001025{
Olli Etuaho8a176262016-08-16 14:23:01 +03001026 if ((elementQualifier.qualifier == EvqAttribute) ||
1027 (elementQualifier.qualifier == EvqVertexIn) ||
1028 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +03001029 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001030 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +03001031 TType(elementQualifier).getQualifierString());
1032 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001033 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001034
Olli Etuaho8a176262016-08-16 14:23:01 +03001035 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001036}
1037
Olli Etuaho8a176262016-08-16 14:23:01 +03001038// See if this element type can be formed into an array.
Olli Etuahoe0803872017-08-23 15:30:23 +03001039bool TParseContext::checkArrayElementIsNotArray(const TSourceLoc &line,
1040 const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001041{
Olli Etuaho7881cfd2017-08-23 18:00:21 +03001042 if (mShaderVersion < 310 && elementType.isArray())
Jamie Madill06145232015-05-13 13:10:01 -04001043 {
Olli Etuaho72e35892018-06-20 11:43:08 +03001044 TInfoSinkBase typeString;
1045 typeString << TType(elementType);
1046 error(line, "cannot declare arrays of arrays", typeString.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001047 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001048 }
Olli Etuahoe0803872017-08-23 15:30:23 +03001049 return true;
1050}
1051
1052// Check if this qualified element type can be formed into an array. This is only called when array
1053// brackets are associated with an identifier in a declaration, like this:
1054// float a[2];
1055// Similar checks are done in addFullySpecifiedType for array declarations where the array brackets
1056// are associated with the type, like this:
1057// float[2] a;
1058bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
1059 const TPublicType &elementType)
1060{
1061 if (!checkArrayElementIsNotArray(indexLocation, elementType))
1062 {
1063 return false;
1064 }
Olli Etuahocc36b982015-07-10 14:14:18 +03001065 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
1066 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
1067 // 4.3.4).
Jiawei Shao492b5f52017-12-13 09:39:27 +08001068 // Geometry shader requires each user-defined input be declared as arrays or inside input
1069 // blocks declared as arrays (GL_EXT_geometry_shader section 11.1gs.4.3). For the purposes of
1070 // interface matching, such variables and blocks are treated as though they were not declared
1071 // as arrays (GL_EXT_geometry_shader section 7.4.1).
Martin Radev4a9cd802016-09-01 16:51:51 +03001072 if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
Jiawei Shao492b5f52017-12-13 09:39:27 +08001073 sh::IsVarying(elementType.qualifier) &&
1074 !IsGeometryShaderInput(mShaderType, elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +03001075 {
Olli Etuaho72e35892018-06-20 11:43:08 +03001076 TInfoSinkBase typeString;
1077 typeString << TType(elementType);
Olli Etuahoe0803872017-08-23 15:30:23 +03001078 error(indexLocation, "cannot declare arrays of structs of this qualifier",
Olli Etuaho72e35892018-06-20 11:43:08 +03001079 typeString.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001080 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +03001081 }
Olli Etuahoe0803872017-08-23 15:30:23 +03001082 return checkIsValidQualifierForArray(indexLocation, elementType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001083}
1084
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001085// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +03001086void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
Olli Etuahofbb1c792018-01-19 16:26:59 +02001087 const ImmutableString &identifier,
Olli Etuaho55bde912017-10-25 13:41:13 +03001088 TType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001089{
Olli Etuaho3739d232015-04-08 12:23:44 +03001090 ASSERT(type != nullptr);
Olli Etuaho55bde912017-10-25 13:41:13 +03001091 if (type->getQualifier() == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +00001092 {
1093 // Make the qualifier make sense.
Olli Etuaho55bde912017-10-25 13:41:13 +03001094 type->setQualifier(EvqTemporary);
Olli Etuaho3739d232015-04-08 12:23:44 +03001095
1096 // Generate informative error messages for ESSL1.
1097 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001098 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +00001099 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05301100 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001101 "structures containing arrays may not be declared constant since they cannot be "
1102 "initialized",
Olli Etuahofbb1c792018-01-19 16:26:59 +02001103 identifier);
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +00001104 }
1105 else
1106 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02001107 error(line, "variables with qualifier 'const' must be initialized", identifier);
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +00001108 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001109 }
Olli Etuaho55bde912017-10-25 13:41:13 +03001110 // This will make the type sized if it isn't sized yet.
Olli Etuahofbb1c792018-01-19 16:26:59 +02001111 checkIsNotUnsizedArray(line, "implicitly sized arrays need to be initialized", identifier,
1112 type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001113}
1114
Olli Etuaho2935c582015-04-08 14:32:06 +03001115// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001116// and update the symbol table.
1117//
Olli Etuaho2935c582015-04-08 14:32:06 +03001118// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001119//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001120bool TParseContext::declareVariable(const TSourceLoc &line,
Olli Etuahofbb1c792018-01-19 16:26:59 +02001121 const ImmutableString &identifier,
Olli Etuahob60d30f2018-01-16 12:31:06 +02001122 const TType *type,
Olli Etuaho2935c582015-04-08 14:32:06 +03001123 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001124{
Olli Etuaho2935c582015-04-08 14:32:06 +03001125 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001126
Olli Etuahofbb1c792018-01-19 16:26:59 +02001127 (*variable) = new TVariable(&symbolTable, identifier, type, SymbolType::UserDefined);
Olli Etuaho195be942017-12-04 23:40:14 +02001128
Olli Etuahoa78092c2018-09-26 14:16:13 +03001129 ASSERT(type->getLayoutQualifier().index == -1 ||
1130 (isExtensionEnabled(TExtension::EXT_blend_func_extended) &&
1131 mShaderType == GL_FRAGMENT_SHADER && mShaderVersion >= 300));
1132 if (type->getQualifier() == EvqFragmentOut)
1133 {
1134 if (type->getLayoutQualifier().index != -1 && type->getLayoutQualifier().location == -1)
1135 {
1136 error(line,
1137 "If index layout qualifier is specified for a fragment output, location must "
1138 "also be specified.",
1139 "index");
1140 return false;
1141 }
1142 }
1143 else
1144 {
1145 checkIndexIsNotSpecified(line, type->getLayoutQualifier().index);
1146 }
1147
Olli Etuahob60d30f2018-01-16 12:31:06 +02001148 checkBindingIsValid(line, *type);
Olli Etuaho43364892017-02-13 16:00:12 +00001149
Olli Etuaho856c4972016-08-08 11:38:39 +03001150 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001151
Olli Etuaho2935c582015-04-08 14:32:06 +03001152 // gl_LastFragData may be redeclared with a new precision qualifier
Olli Etuahofbb1c792018-01-19 16:26:59 +02001153 if (type->isArray() && identifier.beginsWith("gl_LastFragData"))
Olli Etuaho2935c582015-04-08 14:32:06 +03001154 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001155 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
Olli Etuahofbb1c792018-01-19 16:26:59 +02001156 symbolTable.findBuiltIn(ImmutableString("gl_MaxDrawBuffers"), mShaderVersion));
Olli Etuahob60d30f2018-01-16 12:31:06 +02001157 if (type->isArrayOfArrays())
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001158 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02001159 error(line, "redeclaration of gl_LastFragData as an array of arrays", identifier);
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001160 return false;
1161 }
Olli Etuahob60d30f2018-01-16 12:31:06 +02001162 else if (static_cast<int>(type->getOutermostArraySize()) ==
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001163 maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +03001164 {
Olli Etuahodd21ecf2018-01-10 12:42:09 +02001165 if (const TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +03001166 {
Olli Etuaho54a29ff2017-11-28 17:35:20 +02001167 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->extension());
Olli Etuaho2935c582015-04-08 14:32:06 +03001168 }
1169 }
1170 else
1171 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001172 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
Olli Etuahofbb1c792018-01-19 16:26:59 +02001173 identifier);
Olli Etuaho2935c582015-04-08 14:32:06 +03001174 return false;
1175 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001176 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001177
Olli Etuaho8a176262016-08-16 14:23:01 +03001178 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +03001179 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001180
Olli Etuaho437664b2018-02-28 15:38:14 +02001181 if (!symbolTable.declare(*variable))
Olli Etuaho2935c582015-04-08 14:32:06 +03001182 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02001183 error(line, "redefinition", identifier);
Olli Etuaho2935c582015-04-08 14:32:06 +03001184 return false;
1185 }
1186
Olli Etuahob60d30f2018-01-16 12:31:06 +02001187 if (!checkIsNonVoid(line, identifier, type->getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +03001188 return false;
1189
1190 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001191}
1192
Martin Radev70866b82016-07-22 15:27:42 +03001193void TParseContext::checkIsParameterQualifierValid(
1194 const TSourceLoc &line,
1195 const TTypeQualifierBuilder &typeQualifierBuilder,
1196 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301197{
Olli Etuahocce89652017-06-19 16:04:09 +03001198 // The only parameter qualifiers a parameter can have are in, out, inout or const.
Olli Etuaho77ba4082016-12-16 12:01:18 +00001199 TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03001200
1201 if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301202 {
Martin Radev2cc85b32016-08-05 16:22:53 +03001203 checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type);
1204 }
1205
1206 if (!IsImage(type->getBasicType()))
1207 {
Olli Etuaho43364892017-02-13 16:00:12 +00001208 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line);
Martin Radev2cc85b32016-08-05 16:22:53 +03001209 }
1210 else
1211 {
1212 type->setMemoryQualifier(typeQualifier.memoryQualifier);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001213 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001214
Martin Radev70866b82016-07-22 15:27:42 +03001215 type->setQualifier(typeQualifier.qualifier);
1216
1217 if (typeQualifier.precision != EbpUndefined)
1218 {
1219 type->setPrecision(typeQualifier.precision);
1220 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001221}
1222
Olli Etuaho703671e2017-11-08 17:47:18 +02001223template <size_t size>
1224bool TParseContext::checkCanUseOneOfExtensions(const TSourceLoc &line,
1225 const std::array<TExtension, size> &extensions)
1226{
1227 ASSERT(!extensions.empty());
1228 const TExtensionBehavior &extBehavior = extensionBehavior();
1229
1230 bool canUseWithWarning = false;
1231 bool canUseWithoutWarning = false;
1232
1233 const char *errorMsgString = "";
1234 TExtension errorMsgExtension = TExtension::UNDEFINED;
1235
1236 for (TExtension extension : extensions)
1237 {
1238 auto extIter = extBehavior.find(extension);
1239 if (canUseWithWarning)
1240 {
1241 // We already have an extension that we can use, but with a warning.
1242 // See if we can use the alternative extension without a warning.
1243 if (extIter == extBehavior.end())
1244 {
1245 continue;
1246 }
1247 if (extIter->second == EBhEnable || extIter->second == EBhRequire)
1248 {
1249 canUseWithoutWarning = true;
1250 break;
1251 }
1252 continue;
1253 }
1254 if (extIter == extBehavior.end())
1255 {
1256 errorMsgString = "extension is not supported";
1257 errorMsgExtension = extension;
1258 }
1259 else if (extIter->second == EBhUndefined || extIter->second == EBhDisable)
1260 {
1261 errorMsgString = "extension is disabled";
1262 errorMsgExtension = extension;
1263 }
1264 else if (extIter->second == EBhWarn)
1265 {
1266 errorMsgExtension = extension;
1267 canUseWithWarning = true;
1268 }
1269 else
1270 {
1271 ASSERT(extIter->second == EBhEnable || extIter->second == EBhRequire);
1272 canUseWithoutWarning = true;
1273 break;
1274 }
1275 }
1276
1277 if (canUseWithoutWarning)
1278 {
1279 return true;
1280 }
1281 if (canUseWithWarning)
1282 {
1283 warning(line, "extension is being used", GetExtensionNameString(errorMsgExtension));
1284 return true;
1285 }
1286 error(line, errorMsgString, GetExtensionNameString(errorMsgExtension));
1287 return false;
1288}
1289
1290template bool TParseContext::checkCanUseOneOfExtensions(
1291 const TSourceLoc &line,
1292 const std::array<TExtension, 1> &extensions);
1293template bool TParseContext::checkCanUseOneOfExtensions(
1294 const TSourceLoc &line,
1295 const std::array<TExtension, 2> &extensions);
1296template bool TParseContext::checkCanUseOneOfExtensions(
1297 const TSourceLoc &line,
1298 const std::array<TExtension, 3> &extensions);
1299
Olli Etuaho2a1e8f92017-07-14 11:49:36 +03001300bool TParseContext::checkCanUseExtension(const TSourceLoc &line, TExtension extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001301{
Olli Etuaho2a1e8f92017-07-14 11:49:36 +03001302 ASSERT(extension != TExtension::UNDEFINED);
Corentin Wallez1d33c212017-11-13 10:21:39 -08001303 return checkCanUseOneOfExtensions(line, std::array<TExtension, 1u>{{extension}});
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001304}
1305
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001306// ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause
1307// compile-time or link-time errors are the same whether or not the declaration is empty".
1308// This function implements all the checks that are done on qualifiers regardless of if the
1309// declaration is empty.
1310void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier,
1311 const sh::TLayoutQualifier &layoutQualifier,
1312 const TSourceLoc &location)
1313{
1314 if (qualifier == EvqShared && !layoutQualifier.isEmpty())
1315 {
1316 error(location, "Shared memory declarations cannot have layout specified", "layout");
1317 }
1318
1319 if (layoutQualifier.matrixPacking != EmpUnspecified)
1320 {
1321 error(location, "layout qualifier only valid for interface blocks",
1322 getMatrixPackingString(layoutQualifier.matrixPacking));
1323 return;
1324 }
1325
1326 if (layoutQualifier.blockStorage != EbsUnspecified)
1327 {
1328 error(location, "layout qualifier only valid for interface blocks",
1329 getBlockStorageString(layoutQualifier.blockStorage));
1330 return;
1331 }
1332
1333 if (qualifier == EvqFragmentOut)
1334 {
1335 if (layoutQualifier.location != -1 && layoutQualifier.yuv == true)
1336 {
1337 error(location, "invalid layout qualifier combination", "yuv");
1338 return;
1339 }
1340 }
1341 else
1342 {
1343 checkYuvIsNotSpecified(location, layoutQualifier.yuv);
1344 }
1345
Olli Etuaho95468d12017-05-04 11:14:34 +03001346 // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous
1347 // parsing steps. So it needs to be checked here.
Mingyu Hu7d64c482019-03-12 14:27:40 -07001348 if (isExtensionEnabled(TExtension::OVR_multiview2) && mShaderVersion < 300 &&
Olli Etuaho2a1e8f92017-07-14 11:49:36 +03001349 qualifier == EvqVertexIn)
Olli Etuaho95468d12017-05-04 11:14:34 +03001350 {
1351 error(location, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
1352 }
1353
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001354 bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut;
Jiawei Shao4cc89e22017-08-31 14:25:54 +08001355 if (mShaderVersion >= 310)
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001356 {
Jiawei Shao4cc89e22017-08-31 14:25:54 +08001357 canHaveLocation = canHaveLocation || qualifier == EvqUniform || IsVarying(qualifier);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001358 // We're not checking whether the uniform location is in range here since that depends on
1359 // the type of the variable.
1360 // The type can only be fully determined for non-empty declarations.
1361 }
1362 if (!canHaveLocation)
1363 {
1364 checkLocationIsNotSpecified(location, layoutQualifier);
1365 }
1366}
1367
jchen104cdac9e2017-05-08 11:01:20 +08001368void TParseContext::atomicCounterQualifierErrorCheck(const TPublicType &publicType,
1369 const TSourceLoc &location)
1370{
1371 if (publicType.precision != EbpHigh)
1372 {
1373 error(location, "Can only be highp", "atomic counter");
1374 }
1375 // dEQP enforces compile error if location is specified. See uniform_location.test.
1376 if (publicType.layoutQualifier.location != -1)
1377 {
1378 error(location, "location must not be set for atomic_uint", "layout");
1379 }
1380 if (publicType.layoutQualifier.binding == -1)
1381 {
1382 error(location, "no binding specified", "atomic counter");
1383 }
1384}
1385
Olli Etuaho55bde912017-10-25 13:41:13 +03001386void TParseContext::emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location)
Martin Radevb8b01222016-11-20 23:25:53 +02001387{
Olli Etuaho55bde912017-10-25 13:41:13 +03001388 if (type.isUnsizedArray())
Martin Radevb8b01222016-11-20 23:25:53 +02001389 {
1390 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1391 // error. It is assumed that this applies to empty declarations as well.
1392 error(location, "empty array declaration needs to specify a size", "");
1393 }
Olli Etuahoa78092c2018-09-26 14:16:13 +03001394
1395 if (type.getQualifier() != EvqFragmentOut)
1396 {
1397 checkIndexIsNotSpecified(location, type.getLayoutQualifier().index);
1398 }
Martin Radevb8b01222016-11-20 23:25:53 +02001399}
1400
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001401// These checks are done for all declarations that are non-empty. They're done for non-empty
1402// declarations starting a declarator list, and declarators that follow an empty declaration.
1403void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
1404 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -04001405{
Olli Etuahofa33d582015-04-09 14:33:12 +03001406 switch (publicType.qualifier)
1407 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001408 case EvqVaryingIn:
1409 case EvqVaryingOut:
1410 case EvqAttribute:
1411 case EvqVertexIn:
1412 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +03001413 case EvqComputeIn:
Martin Radev4a9cd802016-09-01 16:51:51 +03001414 if (publicType.getBasicType() == EbtStruct)
Jamie Madillb98c3a82015-07-23 14:26:04 -04001415 {
1416 error(identifierLocation, "cannot be used with a structure",
1417 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +03001418 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001419 }
Jiajia Qinbc585152017-06-23 15:42:17 +08001420 break;
1421 case EvqBuffer:
1422 if (publicType.getBasicType() != EbtInterfaceBlock)
1423 {
1424 error(identifierLocation,
1425 "cannot declare buffer variables at global scope(outside a block)",
1426 getQualifierString(publicType.qualifier));
1427 return;
1428 }
1429 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001430 default:
1431 break;
Olli Etuahofa33d582015-04-09 14:33:12 +03001432 }
jchen10cc2a10e2017-05-03 14:05:12 +08001433 std::string reason(getBasicString(publicType.getBasicType()));
1434 reason += "s must be uniform";
Jamie Madillb98c3a82015-07-23 14:26:04 -04001435 if (publicType.qualifier != EvqUniform &&
jchen10cc2a10e2017-05-03 14:05:12 +08001436 !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str()))
Martin Radev2cc85b32016-08-05 16:22:53 +03001437 {
1438 return;
1439 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001440
Andrei Volykhina5527072017-03-22 16:46:30 +03001441 if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal &&
1442 publicType.qualifier != EvqConst) &&
1443 publicType.getBasicType() == EbtYuvCscStandardEXT)
1444 {
1445 error(identifierLocation, "cannot be used with a yuvCscStandardEXT",
1446 getQualifierString(publicType.qualifier));
1447 return;
1448 }
1449
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001450 if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform)
1451 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001452 // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized.
1453 // But invalid shaders may still reach here with an unsized array declaration.
Olli Etuaho55bde912017-10-25 13:41:13 +03001454 TType type(publicType);
1455 if (!type.isUnsizedArray())
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001456 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001457 checkUniformLocationInRange(identifierLocation, type.getLocationCount(),
1458 publicType.layoutQualifier);
1459 }
1460 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001461
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001462 // check for layout qualifier issues
1463 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
Andrei Volykhina5527072017-03-22 16:46:30 +03001464
Martin Radev2cc85b32016-08-05 16:22:53 +03001465 if (IsImage(publicType.getBasicType()))
1466 {
1467
1468 switch (layoutQualifier.imageInternalFormat)
1469 {
1470 case EiifRGBA32F:
1471 case EiifRGBA16F:
1472 case EiifR32F:
1473 case EiifRGBA8:
1474 case EiifRGBA8_SNORM:
1475 if (!IsFloatImage(publicType.getBasicType()))
1476 {
1477 error(identifierLocation,
1478 "internal image format requires a floating image type",
1479 getBasicString(publicType.getBasicType()));
1480 return;
1481 }
1482 break;
1483 case EiifRGBA32I:
1484 case EiifRGBA16I:
1485 case EiifRGBA8I:
1486 case EiifR32I:
1487 if (!IsIntegerImage(publicType.getBasicType()))
1488 {
1489 error(identifierLocation,
1490 "internal image format requires an integer image type",
1491 getBasicString(publicType.getBasicType()));
1492 return;
1493 }
1494 break;
1495 case EiifRGBA32UI:
1496 case EiifRGBA16UI:
1497 case EiifRGBA8UI:
1498 case EiifR32UI:
1499 if (!IsUnsignedImage(publicType.getBasicType()))
1500 {
1501 error(identifierLocation,
1502 "internal image format requires an unsigned image type",
1503 getBasicString(publicType.getBasicType()));
1504 return;
1505 }
1506 break;
1507 case EiifUnspecified:
1508 error(identifierLocation, "layout qualifier", "No image internal format specified");
1509 return;
1510 default:
1511 error(identifierLocation, "layout qualifier", "unrecognized token");
1512 return;
1513 }
1514
1515 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
1516 switch (layoutQualifier.imageInternalFormat)
1517 {
1518 case EiifR32F:
1519 case EiifR32I:
1520 case EiifR32UI:
1521 break;
1522 default:
1523 if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
1524 {
1525 error(identifierLocation, "layout qualifier",
1526 "Except for images with the r32f, r32i and r32ui format qualifiers, "
1527 "image variables must be qualified readonly and/or writeonly");
1528 return;
1529 }
1530 break;
1531 }
1532 }
1533 else
1534 {
Olli Etuaho43364892017-02-13 16:00:12 +00001535 checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat);
Olli Etuaho43364892017-02-13 16:00:12 +00001536 checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
1537 }
jchen104cdac9e2017-05-08 11:01:20 +08001538
1539 if (IsAtomicCounter(publicType.getBasicType()))
1540 {
1541 atomicCounterQualifierErrorCheck(publicType, identifierLocation);
1542 }
1543 else
1544 {
1545 checkOffsetIsNotSpecified(identifierLocation, layoutQualifier.offset);
1546 }
Olli Etuaho43364892017-02-13 16:00:12 +00001547}
Martin Radev2cc85b32016-08-05 16:22:53 +03001548
Olli Etuaho43364892017-02-13 16:00:12 +00001549void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type)
1550{
1551 TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001552 // Note that the ESSL 3.10 section 4.4.5 is not particularly clear on how the binding qualifier
1553 // on arrays of arrays should be handled. We interpret the spec so that the binding value is
1554 // incremented for each element of the innermost nested arrays. This is in line with how arrays
1555 // of arrays of blocks are specified to behave in GLSL 4.50 and a conservative interpretation
1556 // when it comes to which shaders are accepted by the compiler.
1557 int arrayTotalElementCount = type.getArraySizeProduct();
Olli Etuaho43364892017-02-13 16:00:12 +00001558 if (IsImage(type.getBasicType()))
1559 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001560 checkImageBindingIsValid(identifierLocation, layoutQualifier.binding,
1561 arrayTotalElementCount);
Olli Etuaho43364892017-02-13 16:00:12 +00001562 }
1563 else if (IsSampler(type.getBasicType()))
1564 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001565 checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding,
1566 arrayTotalElementCount);
Olli Etuaho43364892017-02-13 16:00:12 +00001567 }
jchen104cdac9e2017-05-08 11:01:20 +08001568 else if (IsAtomicCounter(type.getBasicType()))
1569 {
1570 checkAtomicCounterBindingIsValid(identifierLocation, layoutQualifier.binding);
1571 }
Olli Etuaho43364892017-02-13 16:00:12 +00001572 else
1573 {
1574 ASSERT(!IsOpaqueType(type.getBasicType()));
1575 checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
Martin Radev2cc85b32016-08-05 16:22:53 +03001576 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001577}
1578
Olli Etuaho856c4972016-08-08 11:38:39 +03001579void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
Olli Etuahofbb1c792018-01-19 16:26:59 +02001580 const ImmutableString &layoutQualifierName,
Olli Etuaho856c4972016-08-08 11:38:39 +03001581 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001582{
1583
1584 if (mShaderVersion < versionRequired)
1585 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02001586 error(location, "invalid layout qualifier: not supported", layoutQualifierName);
Martin Radev802abe02016-08-04 17:48:32 +03001587 }
1588}
1589
Olli Etuaho856c4972016-08-08 11:38:39 +03001590bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1591 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001592{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001593 const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
Martin Radev802abe02016-08-04 17:48:32 +03001594 for (size_t i = 0u; i < localSize.size(); ++i)
1595 {
1596 if (localSize[i] != -1)
1597 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001598 error(location,
1599 "invalid layout qualifier: only valid when used with 'in' in a compute shader "
1600 "global layout declaration",
1601 getWorkGroupSizeString(i));
Olli Etuaho8a176262016-08-16 14:23:01 +03001602 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001603 }
1604 }
1605
Olli Etuaho8a176262016-08-16 14:23:01 +03001606 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001607}
1608
Olli Etuaho43364892017-02-13 16:00:12 +00001609void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
Martin Radev2cc85b32016-08-05 16:22:53 +03001610 TLayoutImageInternalFormat internalFormat)
1611{
1612 if (internalFormat != EiifUnspecified)
1613 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001614 error(location, "invalid layout qualifier: only valid when used with images",
1615 getImageInternalFormatString(internalFormat));
Martin Radev2cc85b32016-08-05 16:22:53 +03001616 }
Olli Etuaho43364892017-02-13 16:00:12 +00001617}
1618
Olli Etuahoa78092c2018-09-26 14:16:13 +03001619void TParseContext::checkIndexIsNotSpecified(const TSourceLoc &location, int index)
1620{
1621 if (index != -1)
1622 {
1623 error(location,
1624 "invalid layout qualifier: only valid when used with a fragment shader output in "
1625 "ESSL version >= 3.00 and EXT_blend_func_extended is enabled",
1626 "index");
1627 }
1628}
1629
Olli Etuaho43364892017-02-13 16:00:12 +00001630void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
1631{
1632 if (binding != -1)
1633 {
1634 error(location,
1635 "invalid layout qualifier: only valid when used with opaque types or blocks",
1636 "binding");
1637 }
1638}
1639
jchen104cdac9e2017-05-08 11:01:20 +08001640void TParseContext::checkOffsetIsNotSpecified(const TSourceLoc &location, int offset)
1641{
1642 if (offset != -1)
1643 {
1644 error(location, "invalid layout qualifier: only valid when used with atomic counters",
1645 "offset");
1646 }
1647}
1648
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001649void TParseContext::checkImageBindingIsValid(const TSourceLoc &location,
1650 int binding,
1651 int arrayTotalElementCount)
Olli Etuaho43364892017-02-13 16:00:12 +00001652{
1653 // Expects arraySize to be 1 when setting binding for only a single variable.
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001654 if (binding >= 0 && binding + arrayTotalElementCount > mMaxImageUnits)
Olli Etuaho43364892017-02-13 16:00:12 +00001655 {
1656 error(location, "image binding greater than gl_MaxImageUnits", "binding");
1657 }
1658}
1659
1660void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location,
1661 int binding,
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001662 int arrayTotalElementCount)
Olli Etuaho43364892017-02-13 16:00:12 +00001663{
1664 // Expects arraySize to be 1 when setting binding for only a single variable.
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001665 if (binding >= 0 && binding + arrayTotalElementCount > mMaxCombinedTextureImageUnits)
Olli Etuaho43364892017-02-13 16:00:12 +00001666 {
1667 error(location, "sampler binding greater than maximum texture units", "binding");
1668 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001669}
1670
Jiajia Qinbc585152017-06-23 15:42:17 +08001671void TParseContext::checkBlockBindingIsValid(const TSourceLoc &location,
1672 const TQualifier &qualifier,
1673 int binding,
1674 int arraySize)
jchen10af713a22017-04-19 09:10:56 +08001675{
1676 int size = (arraySize == 0 ? 1 : arraySize);
Jiajia Qinbc585152017-06-23 15:42:17 +08001677 if (qualifier == EvqUniform)
jchen10af713a22017-04-19 09:10:56 +08001678 {
Jiajia Qinbc585152017-06-23 15:42:17 +08001679 if (binding + size > mMaxUniformBufferBindings)
1680 {
1681 error(location, "uniform block binding greater than MAX_UNIFORM_BUFFER_BINDINGS",
1682 "binding");
1683 }
1684 }
1685 else if (qualifier == EvqBuffer)
1686 {
1687 if (binding + size > mMaxShaderStorageBufferBindings)
1688 {
1689 error(location,
1690 "shader storage block binding greater than MAX_SHADER_STORAGE_BUFFER_BINDINGS",
1691 "binding");
1692 }
jchen10af713a22017-04-19 09:10:56 +08001693 }
1694}
jchen104cdac9e2017-05-08 11:01:20 +08001695void TParseContext::checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding)
1696{
1697 if (binding >= mMaxAtomicCounterBindings)
1698 {
1699 error(location, "atomic counter binding greater than gl_MaxAtomicCounterBindings",
1700 "binding");
1701 }
1702}
jchen10af713a22017-04-19 09:10:56 +08001703
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001704void TParseContext::checkUniformLocationInRange(const TSourceLoc &location,
1705 int objectLocationCount,
1706 const TLayoutQualifier &layoutQualifier)
1707{
1708 int loc = layoutQualifier.location;
1709 if (loc >= 0 && loc + objectLocationCount > mMaxUniformLocations)
1710 {
1711 error(location, "Uniform location out of range", "location");
1712 }
1713}
1714
Andrei Volykhina5527072017-03-22 16:46:30 +03001715void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv)
1716{
1717 if (yuv != false)
1718 {
1719 error(location, "invalid layout qualifier: only valid on program outputs", "yuv");
1720 }
1721}
1722
Jiajia Qinbc585152017-06-23 15:42:17 +08001723void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandidate,
1724 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001725{
1726 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1727 {
Olli Etuahod4bd9632018-03-08 16:32:44 +02001728 TQualifier qual = fnCandidate->getParam(i)->getType().getQualifier();
Jiajia Qinbc585152017-06-23 15:42:17 +08001729 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho94bbed12018-03-20 14:44:53 +02001730 bool argumentIsRead = (IsQualifierUnspecified(qual) || qual == EvqIn || qual == EvqInOut ||
1731 qual == EvqConstReadOnly);
1732 if (argumentIsRead)
Jiajia Qinbc585152017-06-23 15:42:17 +08001733 {
Olli Etuaho94bbed12018-03-20 14:44:53 +02001734 markStaticReadIfSymbol(argument);
1735 if (!IsImage(argument->getBasicType()))
Jiajia Qinbc585152017-06-23 15:42:17 +08001736 {
Olli Etuaho94bbed12018-03-20 14:44:53 +02001737 if (argument->getMemoryQualifier().writeonly)
1738 {
1739 error(argument->getLine(),
1740 "Writeonly value cannot be passed for 'in' or 'inout' parameters.",
1741 fnCall->functionName());
1742 return;
1743 }
Jiajia Qinbc585152017-06-23 15:42:17 +08001744 }
1745 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001746 if (qual == EvqOut || qual == EvqInOut)
1747 {
Olli Etuaho8a176262016-08-16 14:23:01 +03001748 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001749 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001750 error(argument->getLine(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00001751 "Constant value cannot be passed for 'out' or 'inout' parameters.",
Olli Etuaho0c371002017-12-13 17:00:25 +04001752 fnCall->functionName());
Olli Etuaho383b7912016-08-05 11:22:59 +03001753 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001754 }
1755 }
1756 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001757}
1758
Martin Radev70866b82016-07-22 15:27:42 +03001759void TParseContext::checkInvariantVariableQualifier(bool invariant,
1760 const TQualifier qualifier,
1761 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001762{
Martin Radev70866b82016-07-22 15:27:42 +03001763 if (!invariant)
1764 return;
1765
1766 if (mShaderVersion < 300)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001767 {
Martin Radev70866b82016-07-22 15:27:42 +03001768 // input variables in the fragment shader can be also qualified as invariant
1769 if (!sh::CanBeInvariantESSL1(qualifier))
1770 {
1771 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1772 }
1773 }
1774 else
1775 {
1776 if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
1777 {
1778 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1779 }
Olli Etuaho37ad4742015-04-27 13:18:50 +03001780 }
1781}
1782
Olli Etuaho2a1e8f92017-07-14 11:49:36 +03001783bool TParseContext::isExtensionEnabled(TExtension extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001784{
Olli Etuaho2a1e8f92017-07-14 11:49:36 +03001785 return IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001786}
1787
Jamie Madillb98c3a82015-07-23 14:26:04 -04001788void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1789 const char *extName,
1790 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001791{
Geoff Lang197d5292018-04-25 14:29:00 -04001792 angle::pp::SourceLocation srcLoc;
Jamie Madill075edd82013-07-08 13:30:19 -04001793 srcLoc.file = loc.first_file;
1794 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001795 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001796}
1797
Jamie Madillb98c3a82015-07-23 14:26:04 -04001798void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1799 const char *name,
1800 const char *value,
1801 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001802{
Geoff Lang197d5292018-04-25 14:29:00 -04001803 angle::pp::SourceLocation srcLoc;
Jamie Madill075edd82013-07-08 13:30:19 -04001804 srcLoc.file = loc.first_file;
1805 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001806 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001807}
1808
Martin Radev4c4c8e72016-08-04 12:25:34 +03001809sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
Martin Radev802abe02016-08-04 17:48:32 +03001810{
Jamie Madill2f294c92017-11-20 14:47:26 -05001811 sh::WorkGroupSize result(-1);
Martin Radev802abe02016-08-04 17:48:32 +03001812 for (size_t i = 0u; i < result.size(); ++i)
1813 {
1814 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1815 {
1816 result[i] = 1;
1817 }
1818 else
1819 {
1820 result[i] = mComputeShaderLocalSize[i];
1821 }
1822 }
1823 return result;
1824}
1825
Olli Etuaho56229f12017-07-10 14:16:33 +03001826TIntermConstantUnion *TParseContext::addScalarLiteral(const TConstantUnion *constantUnion,
1827 const TSourceLoc &line)
1828{
1829 TIntermConstantUnion *node = new TIntermConstantUnion(
1830 constantUnion, TType(constantUnion->getType(), EbpUndefined, EvqConst));
1831 node->setLine(line);
1832 return node;
1833}
1834
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001835/////////////////////////////////////////////////////////////////////////////////
1836//
1837// Non-Errors.
1838//
1839/////////////////////////////////////////////////////////////////////////////////
1840
Jamie Madill5c097022014-08-20 16:38:32 -04001841const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
Olli Etuahofbb1c792018-01-19 16:26:59 +02001842 const ImmutableString &name,
Jamie Madill5c097022014-08-20 16:38:32 -04001843 const TSymbol *symbol)
1844{
Jamie Madill5c097022014-08-20 16:38:32 -04001845 if (!symbol)
1846 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02001847 error(location, "undeclared identifier", name);
Olli Etuaho0f684632017-07-13 12:42:15 +03001848 return nullptr;
Jamie Madill5c097022014-08-20 16:38:32 -04001849 }
Olli Etuaho0f684632017-07-13 12:42:15 +03001850
1851 if (!symbol->isVariable())
Jamie Madill5c097022014-08-20 16:38:32 -04001852 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02001853 error(location, "variable expected", name);
Olli Etuaho0f684632017-07-13 12:42:15 +03001854 return nullptr;
Jamie Madill5c097022014-08-20 16:38:32 -04001855 }
Olli Etuaho0f684632017-07-13 12:42:15 +03001856
1857 const TVariable *variable = static_cast<const TVariable *>(symbol);
1858
Olli Etuaho54a29ff2017-11-28 17:35:20 +02001859 if (variable->extension() != TExtension::UNDEFINED)
Jamie Madill5c097022014-08-20 16:38:32 -04001860 {
Olli Etuaho54a29ff2017-11-28 17:35:20 +02001861 checkCanUseExtension(location, variable->extension());
Jamie Madill5c097022014-08-20 16:38:32 -04001862 }
1863
Olli Etuaho0f684632017-07-13 12:42:15 +03001864 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1865 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
Olli Etuaho59c5b892018-04-03 11:44:50 +03001866 variable->getType().getQualifier() == EvqWorkGroupSize)
Olli Etuaho0f684632017-07-13 12:42:15 +03001867 {
1868 error(location,
1869 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1870 "gl_WorkGroupSize");
1871 }
Jamie Madill5c097022014-08-20 16:38:32 -04001872 return variable;
1873}
1874
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001875TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
Olli Etuahofbb1c792018-01-19 16:26:59 +02001876 const ImmutableString &name,
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001877 const TSymbol *symbol)
1878{
1879 const TVariable *variable = getNamedVariable(location, name, symbol);
1880
Olli Etuaho0f684632017-07-13 12:42:15 +03001881 if (!variable)
1882 {
1883 TIntermTyped *node = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
1884 node->setLine(location);
1885 return node;
1886 }
1887
Jiawei Shao8e4b3552017-08-30 14:20:58 +08001888 const TType &variableType = variable->getType();
Jamie Madill50cf2be2018-06-15 09:46:57 -04001889 TIntermTyped *node = nullptr;
Olli Etuaho56229f12017-07-10 14:16:33 +03001890
Olli Etuahoea22b7a2018-01-04 17:09:11 +02001891 if (variable->getConstPointer() && variableType.canReplaceWithConstantUnion())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001892 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001893 const TConstantUnion *constArray = variable->getConstPointer();
Jiawei Shao8e4b3552017-08-30 14:20:58 +08001894 node = new TIntermConstantUnion(constArray, variableType);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001895 }
Jiawei Shao8e4b3552017-08-30 14:20:58 +08001896 else if (variableType.getQualifier() == EvqWorkGroupSize && mComputeShaderLocalSizeDeclared)
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001897 {
1898 // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
1899 // needs to be added to the AST as a constant and not as a symbol.
1900 sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
1901 TConstantUnion *constArray = new TConstantUnion[3];
1902 for (size_t i = 0; i < 3; ++i)
1903 {
1904 constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
1905 }
1906
Jiawei Shao8e4b3552017-08-30 14:20:58 +08001907 ASSERT(variableType.getBasicType() == EbtUInt);
1908 ASSERT(variableType.getObjectSize() == 3);
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001909
Jiawei Shao8e4b3552017-08-30 14:20:58 +08001910 TType type(variableType);
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001911 type.setQualifier(EvqConst);
Olli Etuaho56229f12017-07-10 14:16:33 +03001912 node = new TIntermConstantUnion(constArray, type);
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001913 }
Jiawei Shao8e4b3552017-08-30 14:20:58 +08001914 else if ((mGeometryShaderInputPrimitiveType != EptUndefined) &&
1915 (variableType.getQualifier() == EvqPerVertexIn))
Jiawei Shaod8105a02017-08-08 09:54:36 +08001916 {
Olli Etuaho94bbed12018-03-20 14:44:53 +02001917 ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr);
1918 node = new TIntermSymbol(symbolTable.getGlInVariableWithArraySize());
Jiawei Shaod8105a02017-08-08 09:54:36 +08001919 }
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001920 else
1921 {
Olli Etuaho195be942017-12-04 23:40:14 +02001922 node = new TIntermSymbol(variable);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001923 }
Olli Etuaho56229f12017-07-10 14:16:33 +03001924 ASSERT(node != nullptr);
1925 node->setLine(location);
1926 return node;
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001927}
1928
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001929// Initializers show up in several places in the grammar. Have one set of
1930// code to handle them here.
1931//
Olli Etuaho914b79a2017-06-19 16:03:19 +03001932// Returns true on success.
Jamie Madillb98c3a82015-07-23 14:26:04 -04001933bool TParseContext::executeInitializer(const TSourceLoc &line,
Olli Etuahofbb1c792018-01-19 16:26:59 +02001934 const ImmutableString &identifier,
Olli Etuahob60d30f2018-01-16 12:31:06 +02001935 TType *type,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001936 TIntermTyped *initializer,
Olli Etuaho13389b62016-10-16 11:48:18 +01001937 TIntermBinary **initNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001938{
Olli Etuaho13389b62016-10-16 11:48:18 +01001939 ASSERT(initNode != nullptr);
1940 ASSERT(*initNode == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001941
Olli Etuahob60d30f2018-01-16 12:31:06 +02001942 if (type->isUnsizedArray())
Olli Etuaho376f1b52015-04-13 13:23:41 +03001943 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001944 // In case initializer is not an array or type has more dimensions than initializer, this
1945 // will default to setting array sizes to 1. We have not checked yet whether the initializer
1946 // actually is an array or not. Having a non-array initializer for an unsized array will
1947 // result in an error later, so we don't generate an error message here.
Kai Ninomiya57ea5332017-11-22 14:04:48 -08001948 auto *arraySizes = initializer->getType().getArraySizes();
Olli Etuahob60d30f2018-01-16 12:31:06 +02001949 type->sizeUnsizedArrays(arraySizes);
1950 }
1951
1952 const TQualifier qualifier = type->getQualifier();
1953
1954 bool constError = false;
1955 if (qualifier == EvqConst)
1956 {
1957 if (EvqConst != initializer->getType().getQualifier())
1958 {
Olli Etuaho72e35892018-06-20 11:43:08 +03001959 TInfoSinkBase reasonStream;
1960 reasonStream << "assigning non-constant to '" << *type << "'";
1961 error(line, reasonStream.c_str(), "=");
Olli Etuahob60d30f2018-01-16 12:31:06 +02001962
1963 // We're still going to declare the variable to avoid extra error messages.
1964 type->setQualifier(EvqTemporary);
1965 constError = true;
1966 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03001967 }
Olli Etuaho195be942017-12-04 23:40:14 +02001968
1969 TVariable *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +03001970 if (!declareVariable(line, identifier, type, &variable))
1971 {
Olli Etuaho914b79a2017-06-19 16:03:19 +03001972 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001973 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001974
Olli Etuahob60d30f2018-01-16 12:31:06 +02001975 if (constError)
1976 {
1977 return false;
1978 }
1979
Olli Etuahob0c645e2015-05-12 14:25:36 +03001980 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001981 if (symbolTable.atGlobalLevel() &&
Olli Etuahoa2d98142017-12-15 14:18:55 +02001982 !ValidateGlobalInitializer(initializer, mShaderVersion, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001983 {
1984 // Error message does not completely match behavior with ESSL 1.00, but
1985 // we want to steer developers towards only using constant expressions.
1986 error(line, "global variable initializers must be constant expressions", "=");
Olli Etuaho914b79a2017-06-19 16:03:19 +03001987 return false;
Olli Etuahob0c645e2015-05-12 14:25:36 +03001988 }
1989 if (globalInitWarning)
1990 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001991 warning(
1992 line,
1993 "global variable initializers should be constant expressions "
1994 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1995 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001996 }
1997
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001998 // identifier must be of type constant, a global, or a temporary
Arun Patole7e7e68d2015-05-22 12:02:25 +05301999 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
2000 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002001 error(line, " cannot initialize this type of qualifier ",
2002 variable->getType().getQualifierString());
Olli Etuaho914b79a2017-06-19 16:03:19 +03002003 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002004 }
Olli Etuahob60d30f2018-01-16 12:31:06 +02002005
2006 TIntermSymbol *intermSymbol = new TIntermSymbol(variable);
2007 intermSymbol->setLine(line);
2008
2009 if (!binaryOpCommonCheck(EOpInitialize, intermSymbol, initializer, line))
2010 {
Olli Etuaho72e35892018-06-20 11:43:08 +03002011 assignError(line, "=", variable->getType(), initializer->getType());
Olli Etuahob60d30f2018-01-16 12:31:06 +02002012 return false;
2013 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002014
Arun Patole7e7e68d2015-05-22 12:02:25 +05302015 if (qualifier == EvqConst)
2016 {
Olli Etuahoea22b7a2018-01-04 17:09:11 +02002017 // Save the constant folded value to the variable if possible.
2018 const TConstantUnion *constArray = initializer->getConstantValue();
2019 if (constArray)
Arun Patole7e7e68d2015-05-22 12:02:25 +05302020 {
Olli Etuahoea22b7a2018-01-04 17:09:11 +02002021 variable->shareConstPointer(constArray);
2022 if (initializer->getType().canReplaceWithConstantUnion())
Olli Etuahob1edc4f2015-11-02 17:20:03 +02002023 {
Olli Etuaho914b79a2017-06-19 16:03:19 +03002024 ASSERT(*initNode == nullptr);
2025 return true;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02002026 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002027 }
2028 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02002029
Olli Etuahob60d30f2018-01-16 12:31:06 +02002030 *initNode = new TIntermBinary(EOpInitialize, intermSymbol, initializer);
Olli Etuaho94bbed12018-03-20 14:44:53 +02002031 markStaticReadIfSymbol(initializer);
Olli Etuahob60d30f2018-01-16 12:31:06 +02002032 (*initNode)->setLine(line);
Olli Etuaho914b79a2017-06-19 16:03:19 +03002033 return true;
2034}
2035
2036TIntermNode *TParseContext::addConditionInitializer(const TPublicType &pType,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002037 const ImmutableString &identifier,
Olli Etuaho914b79a2017-06-19 16:03:19 +03002038 TIntermTyped *initializer,
2039 const TSourceLoc &loc)
2040{
2041 checkIsScalarBool(loc, pType);
2042 TIntermBinary *initNode = nullptr;
Olli Etuahob60d30f2018-01-16 12:31:06 +02002043 TType *type = new TType(pType);
Olli Etuaho55bde912017-10-25 13:41:13 +03002044 if (executeInitializer(loc, identifier, type, initializer, &initNode))
Olli Etuaho914b79a2017-06-19 16:03:19 +03002045 {
2046 // The initializer is valid. The init condition needs to have a node - either the
2047 // initializer node, or a constant node in case the initialized variable is const and won't
2048 // be recorded in the AST.
2049 if (initNode == nullptr)
2050 {
2051 return initializer;
2052 }
2053 else
2054 {
2055 TIntermDeclaration *declaration = new TIntermDeclaration();
2056 declaration->appendDeclarator(initNode);
2057 return declaration;
2058 }
2059 }
2060 return nullptr;
2061}
2062
2063TIntermNode *TParseContext::addLoop(TLoopType type,
2064 TIntermNode *init,
2065 TIntermNode *cond,
2066 TIntermTyped *expr,
2067 TIntermNode *body,
2068 const TSourceLoc &line)
2069{
2070 TIntermNode *node = nullptr;
2071 TIntermTyped *typedCond = nullptr;
2072 if (cond)
2073 {
Olli Etuaho94bbed12018-03-20 14:44:53 +02002074 markStaticReadIfSymbol(cond);
Olli Etuaho914b79a2017-06-19 16:03:19 +03002075 typedCond = cond->getAsTyped();
2076 }
Olli Etuaho94bbed12018-03-20 14:44:53 +02002077 if (expr)
2078 {
2079 markStaticReadIfSymbol(expr);
2080 }
2081 // In case the loop body was not parsed as a block and contains a statement that simply refers
2082 // to a variable, we need to mark it as statically used.
2083 if (body)
2084 {
2085 markStaticReadIfSymbol(body);
2086 }
Olli Etuaho914b79a2017-06-19 16:03:19 +03002087 if (cond == nullptr || typedCond)
2088 {
Olli Etuahocce89652017-06-19 16:04:09 +03002089 if (type == ELoopDoWhile)
2090 {
2091 checkIsScalarBool(line, typedCond);
2092 }
2093 // In the case of other loops, it was checked before that the condition is a scalar boolean.
2094 ASSERT(mDiagnostics->numErrors() > 0 || typedCond == nullptr ||
2095 (typedCond->getBasicType() == EbtBool && !typedCond->isArray() &&
2096 !typedCond->isVector()));
2097
Olli Etuaho3ec75682017-07-05 17:02:55 +03002098 node = new TIntermLoop(type, init, typedCond, expr, EnsureBlock(body));
Olli Etuaho914b79a2017-06-19 16:03:19 +03002099 node->setLine(line);
2100 return node;
2101 }
2102
Olli Etuahocce89652017-06-19 16:04:09 +03002103 ASSERT(type != ELoopDoWhile);
2104
Olli Etuaho914b79a2017-06-19 16:03:19 +03002105 TIntermDeclaration *declaration = cond->getAsDeclarationNode();
2106 ASSERT(declaration);
2107 TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode();
2108 ASSERT(declarator->getLeft()->getAsSymbolNode());
2109
2110 // The condition is a declaration. In the AST representation we don't support declarations as
2111 // loop conditions. Wrap the loop to a block that declares the condition variable and contains
2112 // the loop.
2113 TIntermBlock *block = new TIntermBlock();
2114
2115 TIntermDeclaration *declareCondition = new TIntermDeclaration();
2116 declareCondition->appendDeclarator(declarator->getLeft()->deepCopy());
2117 block->appendStatement(declareCondition);
2118
2119 TIntermBinary *conditionInit = new TIntermBinary(EOpAssign, declarator->getLeft()->deepCopy(),
2120 declarator->getRight()->deepCopy());
Olli Etuaho3ec75682017-07-05 17:02:55 +03002121 TIntermLoop *loop = new TIntermLoop(type, init, conditionInit, expr, EnsureBlock(body));
Olli Etuaho914b79a2017-06-19 16:03:19 +03002122 block->appendStatement(loop);
2123 loop->setLine(line);
2124 block->setLine(line);
2125 return block;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002126}
2127
Olli Etuahocce89652017-06-19 16:04:09 +03002128TIntermNode *TParseContext::addIfElse(TIntermTyped *cond,
2129 TIntermNodePair code,
2130 const TSourceLoc &loc)
2131{
Olli Etuaho56229f12017-07-10 14:16:33 +03002132 bool isScalarBool = checkIsScalarBool(loc, cond);
Olli Etuaho94bbed12018-03-20 14:44:53 +02002133 // In case the conditional statements were not parsed as blocks and contain a statement that
2134 // simply refers to a variable, we need to mark them as statically used.
2135 if (code.node1)
2136 {
2137 markStaticReadIfSymbol(code.node1);
2138 }
2139 if (code.node2)
2140 {
2141 markStaticReadIfSymbol(code.node2);
2142 }
Olli Etuahocce89652017-06-19 16:04:09 +03002143
2144 // For compile time constant conditions, prune the code now.
Olli Etuaho56229f12017-07-10 14:16:33 +03002145 if (isScalarBool && cond->getAsConstantUnion())
Olli Etuahocce89652017-06-19 16:04:09 +03002146 {
2147 if (cond->getAsConstantUnion()->getBConst(0) == true)
2148 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03002149 return EnsureBlock(code.node1);
Olli Etuahocce89652017-06-19 16:04:09 +03002150 }
2151 else
2152 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03002153 return EnsureBlock(code.node2);
Olli Etuahocce89652017-06-19 16:04:09 +03002154 }
2155 }
2156
Olli Etuaho3ec75682017-07-05 17:02:55 +03002157 TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2));
Olli Etuaho94bbed12018-03-20 14:44:53 +02002158 markStaticReadIfSymbol(cond);
Olli Etuahocce89652017-06-19 16:04:09 +03002159 node->setLine(loc);
2160
2161 return node;
2162}
2163
Olli Etuaho0e3aee32016-10-27 12:56:38 +01002164void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
2165{
2166 checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
2167 typeSpecifier->getBasicType());
2168
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002169 if (mShaderVersion < 300 && typeSpecifier->isArray())
Olli Etuaho0e3aee32016-10-27 12:56:38 +01002170 {
2171 error(typeSpecifier->getLine(), "not supported", "first-class array");
2172 typeSpecifier->clearArrayness();
2173 }
2174}
2175
Martin Radev70866b82016-07-22 15:27:42 +03002176TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302177 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002178{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002179 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002180
Martin Radev70866b82016-07-22 15:27:42 +03002181 TPublicType returnType = typeSpecifier;
2182 returnType.qualifier = typeQualifier.qualifier;
2183 returnType.invariant = typeQualifier.invariant;
2184 returnType.layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03002185 returnType.memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03002186 returnType.precision = typeSpecifier.precision;
2187
2188 if (typeQualifier.precision != EbpUndefined)
2189 {
2190 returnType.precision = typeQualifier.precision;
2191 }
2192
Martin Radev4a9cd802016-09-01 16:51:51 +03002193 checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
2194 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03002195
Martin Radev4a9cd802016-09-01 16:51:51 +03002196 checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
2197 typeSpecifier.getLine());
Martin Radev70866b82016-07-22 15:27:42 +03002198
Martin Radev4a9cd802016-09-01 16:51:51 +03002199 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002200
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002201 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002202 {
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002203 if (typeSpecifier.isArray())
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03002204 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002205 error(typeSpecifier.getLine(), "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03002206 returnType.clearArrayness();
2207 }
2208
Martin Radev70866b82016-07-22 15:27:42 +03002209 if (returnType.qualifier == EvqAttribute &&
Martin Radev4a9cd802016-09-01 16:51:51 +03002210 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002211 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002212 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03002213 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002214 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002215
Martin Radev70866b82016-07-22 15:27:42 +03002216 if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
Martin Radev4a9cd802016-09-01 16:51:51 +03002217 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002218 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002219 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03002220 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002221 }
2222 }
2223 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002224 {
Martin Radev70866b82016-07-22 15:27:42 +03002225 if (!returnType.layoutQualifier.isEmpty())
Olli Etuahoabb0c382015-07-13 12:01:12 +03002226 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002227 checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03002228 }
Martin Radev70866b82016-07-22 15:27:42 +03002229 if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
2230 returnType.qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002231 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002232 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
2233 typeSpecifier.getLine());
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002234 }
Martin Radev70866b82016-07-22 15:27:42 +03002235 if (returnType.qualifier == EvqComputeIn)
Martin Radev802abe02016-08-04 17:48:32 +03002236 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002237 error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
Martin Radev802abe02016-08-04 17:48:32 +03002238 "in");
Martin Radev802abe02016-08-04 17:48:32 +03002239 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002240 }
2241
2242 return returnType;
2243}
2244
Olli Etuaho856c4972016-08-08 11:38:39 +03002245void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
2246 const TPublicType &type,
2247 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03002248{
2249 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
Martin Radev4a9cd802016-09-01 16:51:51 +03002250 if (type.getBasicType() == EbtBool)
Olli Etuahocc36b982015-07-10 14:14:18 +03002251 {
2252 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002253 }
2254
2255 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
2256 switch (qualifier)
2257 {
2258 case EvqVertexIn:
2259 // ESSL 3.00 section 4.3.4
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002260 if (type.isArray())
Olli Etuahocc36b982015-07-10 14:14:18 +03002261 {
2262 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002263 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002264 // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03002265 return;
2266 case EvqFragmentOut:
2267 // ESSL 3.00 section 4.3.6
Martin Radev4a9cd802016-09-01 16:51:51 +03002268 if (type.typeSpecifierNonArray.isMatrix())
Olli Etuahocc36b982015-07-10 14:14:18 +03002269 {
2270 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002271 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002272 // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03002273 return;
2274 default:
2275 break;
2276 }
2277
2278 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
2279 // restrictions.
2280 bool typeContainsIntegers =
Martin Radev4a9cd802016-09-01 16:51:51 +03002281 (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
2282 type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
Olli Etuahocc36b982015-07-10 14:14:18 +03002283 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
2284 {
2285 error(qualifierLocation, "must use 'flat' interpolation here",
2286 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002287 }
2288
Martin Radev4a9cd802016-09-01 16:51:51 +03002289 if (type.getBasicType() == EbtStruct)
Olli Etuahocc36b982015-07-10 14:14:18 +03002290 {
2291 // ESSL 3.00 sections 4.3.4 and 4.3.6.
2292 // These restrictions are only implied by the ESSL 3.00 spec, but
2293 // the ESSL 3.10 spec lists these restrictions explicitly.
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002294 if (type.isArray())
Olli Etuahocc36b982015-07-10 14:14:18 +03002295 {
2296 error(qualifierLocation, "cannot be an array of structures",
2297 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002298 }
2299 if (type.isStructureContainingArrays())
2300 {
2301 error(qualifierLocation, "cannot be a structure containing an array",
2302 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002303 }
2304 if (type.isStructureContainingType(EbtStruct))
2305 {
2306 error(qualifierLocation, "cannot be a structure containing a structure",
2307 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002308 }
2309 if (type.isStructureContainingType(EbtBool))
2310 {
2311 error(qualifierLocation, "cannot be a structure containing a bool",
2312 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002313 }
2314 }
2315}
2316
Martin Radev2cc85b32016-08-05 16:22:53 +03002317void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
2318{
2319 if (qualifier.getType() == QtStorage)
2320 {
2321 const TStorageQualifierWrapper &storageQualifier =
2322 static_cast<const TStorageQualifierWrapper &>(qualifier);
2323 if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
2324 !symbolTable.atGlobalLevel())
2325 {
2326 error(storageQualifier.getLine(),
2327 "Local variables can only use the const storage qualifier.",
Olli Etuaho1a3bbaa2018-01-25 11:41:31 +02002328 storageQualifier.getQualifierString());
Martin Radev2cc85b32016-08-05 16:22:53 +03002329 }
2330 }
2331}
2332
Olli Etuaho43364892017-02-13 16:00:12 +00002333void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
Martin Radev2cc85b32016-08-05 16:22:53 +03002334 const TSourceLoc &location)
2335{
Jiajia Qinbc585152017-06-23 15:42:17 +08002336 const std::string reason(
2337 "Only allowed with shader storage blocks, variables declared within shader storage blocks "
2338 "and variables declared as image types.");
Martin Radev2cc85b32016-08-05 16:22:53 +03002339 if (memoryQualifier.readonly)
2340 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002341 error(location, reason.c_str(), "readonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03002342 }
2343 if (memoryQualifier.writeonly)
2344 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002345 error(location, reason.c_str(), "writeonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03002346 }
Martin Radev049edfa2016-11-11 14:35:37 +02002347 if (memoryQualifier.coherent)
2348 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002349 error(location, reason.c_str(), "coherent");
Martin Radev049edfa2016-11-11 14:35:37 +02002350 }
2351 if (memoryQualifier.restrictQualifier)
2352 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002353 error(location, reason.c_str(), "restrict");
Martin Radev049edfa2016-11-11 14:35:37 +02002354 }
2355 if (memoryQualifier.volatileQualifier)
2356 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002357 error(location, reason.c_str(), "volatile");
Martin Radev049edfa2016-11-11 14:35:37 +02002358 }
Martin Radev2cc85b32016-08-05 16:22:53 +03002359}
2360
jchen104cdac9e2017-05-08 11:01:20 +08002361// Make sure there is no offset overlapping, and store the newly assigned offset to "type" in
2362// intermediate tree.
Olli Etuaho55bc9052017-10-25 17:33:06 +03002363void TParseContext::checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend,
2364 const TSourceLoc &loc,
2365 TType *type)
jchen104cdac9e2017-05-08 11:01:20 +08002366{
Olli Etuaho55bc9052017-10-25 17:33:06 +03002367 const size_t size = type->isArray() ? kAtomicCounterArrayStride * type->getArraySizeProduct()
2368 : kAtomicCounterSize;
2369 TLayoutQualifier layoutQualifier = type->getLayoutQualifier();
2370 auto &bindingState = mAtomicCounterBindingStates[layoutQualifier.binding];
jchen104cdac9e2017-05-08 11:01:20 +08002371 int offset;
Olli Etuaho55bc9052017-10-25 17:33:06 +03002372 if (layoutQualifier.offset == -1 || forceAppend)
jchen104cdac9e2017-05-08 11:01:20 +08002373 {
2374 offset = bindingState.appendSpan(size);
2375 }
2376 else
2377 {
Olli Etuaho55bc9052017-10-25 17:33:06 +03002378 offset = bindingState.insertSpan(layoutQualifier.offset, size);
jchen104cdac9e2017-05-08 11:01:20 +08002379 }
2380 if (offset == -1)
2381 {
2382 error(loc, "Offset overlapping", "atomic counter");
2383 return;
2384 }
Olli Etuaho55bc9052017-10-25 17:33:06 +03002385 layoutQualifier.offset = offset;
2386 type->setLayoutQualifier(layoutQualifier);
jchen104cdac9e2017-05-08 11:01:20 +08002387}
2388
Enrico Galliee7ffd92018-12-13 14:07:52 -08002389void TParseContext::checkAtomicCounterOffsetAlignment(const TSourceLoc &location, const TType &type)
2390{
2391 TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
2392
2393 // OpenGL ES 3.1 Table 6.5, Atomic counter offset must be a multiple of 4
2394 if (layoutQualifier.offset % 4 != 0)
2395 {
2396 error(location, "Offset must be multiple of 4", "atomic counter");
2397 }
2398}
2399
Olli Etuaho454c34c2017-10-25 16:35:56 +03002400void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002401 const ImmutableString &token,
Olli Etuaho454c34c2017-10-25 16:35:56 +03002402 TType *type)
2403{
2404 if (IsGeometryShaderInput(mShaderType, type->getQualifier()))
2405 {
2406 if (type->isArray() && type->getOutermostArraySize() == 0u)
2407 {
2408 // Set size for the unsized geometry shader inputs if they are declared after a valid
2409 // input primitive declaration.
2410 if (mGeometryShaderInputPrimitiveType != EptUndefined)
2411 {
Olli Etuaho94bbed12018-03-20 14:44:53 +02002412 ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr);
Olli Etuahoc74ec1a2018-01-09 15:23:28 +02002413 type->sizeOutermostUnsizedArray(
Olli Etuaho94bbed12018-03-20 14:44:53 +02002414 symbolTable.getGlInVariableWithArraySize()->getType().getOutermostArraySize());
Olli Etuaho454c34c2017-10-25 16:35:56 +03002415 }
2416 else
2417 {
2418 // [GLSL ES 3.2 SPEC Chapter 4.4.1.2]
2419 // An input can be declared without an array size if there is a previous layout
2420 // which specifies the size.
2421 error(location,
2422 "Missing a valid input primitive declaration before declaring an unsized "
2423 "array input",
2424 token);
2425 }
2426 }
2427 else if (type->isArray())
2428 {
2429 setGeometryShaderInputArraySize(type->getOutermostArraySize(), location);
2430 }
2431 else
2432 {
2433 error(location, "Geometry shader input variable must be declared as an array", token);
2434 }
2435 }
2436}
2437
Olli Etuaho13389b62016-10-16 11:48:18 +01002438TIntermDeclaration *TParseContext::parseSingleDeclaration(
2439 TPublicType &publicType,
2440 const TSourceLoc &identifierOrTypeLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002441 const ImmutableString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04002442{
Olli Etuahob60d30f2018-01-16 12:31:06 +02002443 TType *type = new TType(publicType);
Kenneth Russellbccc65d2016-07-19 16:48:43 -07002444
Olli Etuahofbb1c792018-01-19 16:26:59 +02002445 checkGeometryShaderInputAndSetArraySize(identifierOrTypeLocation, identifier, type);
Jiawei Shao8e4b3552017-08-30 14:20:58 +08002446
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002447 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2448 identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002449
Jamie Madill50cf2be2018-06-15 09:46:57 -04002450 bool emptyDeclaration = (identifier == "");
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002451 mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration;
Olli Etuahofa33d582015-04-09 14:33:12 +03002452
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002453 TIntermSymbol *symbol = nullptr;
Olli Etuahobab4c082015-04-24 16:38:49 +03002454 if (emptyDeclaration)
2455 {
Olli Etuahob60d30f2018-01-16 12:31:06 +02002456 emptyDeclarationErrorCheck(*type, identifierOrTypeLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002457 // In most cases we don't need to create a symbol node for an empty declaration.
2458 // But if the empty declaration is declaring a struct type, the symbol node will store that.
Olli Etuahob60d30f2018-01-16 12:31:06 +02002459 if (type->getBasicType() == EbtStruct)
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002460 {
Olli Etuaho195be942017-12-04 23:40:14 +02002461 TVariable *emptyVariable =
Jamie Madillb779b122018-06-20 11:46:43 -04002462 new TVariable(&symbolTable, kEmptyImmutableString, type, SymbolType::Empty);
Olli Etuaho195be942017-12-04 23:40:14 +02002463 symbol = new TIntermSymbol(emptyVariable);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002464 }
jchen104cdac9e2017-05-08 11:01:20 +08002465 else if (IsAtomicCounter(publicType.getBasicType()))
2466 {
2467 setAtomicCounterBindingDefaultOffset(publicType, identifierOrTypeLocation);
2468 }
Olli Etuahobab4c082015-04-24 16:38:49 +03002469 }
2470 else
Jamie Madill60ed9812013-06-06 11:56:46 -04002471 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002472 nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002473
Olli Etuahob60d30f2018-01-16 12:31:06 +02002474 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, type);
Jamie Madill60ed9812013-06-06 11:56:46 -04002475
Enrico Galliee7ffd92018-12-13 14:07:52 -08002476 if (IsAtomicCounter(type->getBasicType()))
2477 {
2478 checkAtomicCounterOffsetDoesNotOverlap(false, identifierOrTypeLocation, type);
2479
2480 checkAtomicCounterOffsetAlignment(identifierOrTypeLocation, *type);
2481 }
jchen104cdac9e2017-05-08 11:01:20 +08002482
Olli Etuaho2935c582015-04-08 14:32:06 +03002483 TVariable *variable = nullptr;
Olli Etuaho195be942017-12-04 23:40:14 +02002484 if (declareVariable(identifierOrTypeLocation, identifier, type, &variable))
Olli Etuaho13389b62016-10-16 11:48:18 +01002485 {
Olli Etuaho195be942017-12-04 23:40:14 +02002486 symbol = new TIntermSymbol(variable);
Olli Etuaho13389b62016-10-16 11:48:18 +01002487 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002488 }
2489
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002490 TIntermDeclaration *declaration = new TIntermDeclaration();
2491 declaration->setLine(identifierOrTypeLocation);
2492 if (symbol)
2493 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002494 symbol->setLine(identifierOrTypeLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002495 declaration->appendDeclarator(symbol);
2496 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002497 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002498}
2499
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002500TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(
2501 TPublicType &elementType,
2502 const TSourceLoc &identifierLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002503 const ImmutableString &identifier,
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002504 const TSourceLoc &indexLocation,
2505 const TVector<unsigned int> &arraySizes)
Jamie Madill60ed9812013-06-06 11:56:46 -04002506{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002507 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002508
Olli Etuaho55bde912017-10-25 13:41:13 +03002509 declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier,
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002510 identifierLocation);
2511
Olli Etuaho55bde912017-10-25 13:41:13 +03002512 nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002513
Olli Etuaho55bde912017-10-25 13:41:13 +03002514 checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002515
Olli Etuahob60d30f2018-01-16 12:31:06 +02002516 TType *arrayType = new TType(elementType);
2517 arrayType->makeArrays(arraySizes);
Jamie Madill60ed9812013-06-06 11:56:46 -04002518
Olli Etuahofbb1c792018-01-19 16:26:59 +02002519 checkGeometryShaderInputAndSetArraySize(indexLocation, identifier, arrayType);
Olli Etuaho55bde912017-10-25 13:41:13 +03002520
Olli Etuahob60d30f2018-01-16 12:31:06 +02002521 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, arrayType);
Olli Etuaho55bde912017-10-25 13:41:13 +03002522
Enrico Galliee7ffd92018-12-13 14:07:52 -08002523 if (IsAtomicCounter(arrayType->getBasicType()))
2524 {
2525 checkAtomicCounterOffsetDoesNotOverlap(false, identifierLocation, arrayType);
2526
2527 checkAtomicCounterOffsetAlignment(identifierLocation, *arrayType);
2528 }
jchen104cdac9e2017-05-08 11:01:20 +08002529
Olli Etuaho13389b62016-10-16 11:48:18 +01002530 TIntermDeclaration *declaration = new TIntermDeclaration();
2531 declaration->setLine(identifierLocation);
2532
Olli Etuaho195be942017-12-04 23:40:14 +02002533 TVariable *variable = nullptr;
2534 if (declareVariable(identifierLocation, identifier, arrayType, &variable))
Olli Etuaho13389b62016-10-16 11:48:18 +01002535 {
Olli Etuaho195be942017-12-04 23:40:14 +02002536 TIntermSymbol *symbol = new TIntermSymbol(variable);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002537 symbol->setLine(identifierLocation);
Olli Etuaho13389b62016-10-16 11:48:18 +01002538 declaration->appendDeclarator(symbol);
2539 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002540
Olli Etuaho13389b62016-10-16 11:48:18 +01002541 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002542}
2543
Olli Etuaho13389b62016-10-16 11:48:18 +01002544TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
2545 const TSourceLoc &identifierLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002546 const ImmutableString &identifier,
Olli Etuaho13389b62016-10-16 11:48:18 +01002547 const TSourceLoc &initLocation,
2548 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04002549{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002550 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002551
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002552 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2553 identifierLocation);
2554
2555 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002556
Olli Etuaho13389b62016-10-16 11:48:18 +01002557 TIntermDeclaration *declaration = new TIntermDeclaration();
2558 declaration->setLine(identifierLocation);
2559
2560 TIntermBinary *initNode = nullptr;
Olli Etuahob60d30f2018-01-16 12:31:06 +02002561 TType *type = new TType(publicType);
Olli Etuaho55bde912017-10-25 13:41:13 +03002562 if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04002563 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002564 if (initNode)
2565 {
2566 declaration->appendDeclarator(initNode);
2567 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002568 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002569 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002570}
2571
Olli Etuaho13389b62016-10-16 11:48:18 +01002572TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
Olli Etuaho55bde912017-10-25 13:41:13 +03002573 TPublicType &elementType,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002574 const TSourceLoc &identifierLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002575 const ImmutableString &identifier,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002576 const TSourceLoc &indexLocation,
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002577 const TVector<unsigned int> &arraySizes,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002578 const TSourceLoc &initLocation,
2579 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002580{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002581 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002582
Olli Etuaho55bde912017-10-25 13:41:13 +03002583 declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier,
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002584 identifierLocation);
2585
Olli Etuaho55bde912017-10-25 13:41:13 +03002586 nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002587
Olli Etuaho55bde912017-10-25 13:41:13 +03002588 checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002589
Olli Etuahob60d30f2018-01-16 12:31:06 +02002590 TType *arrayType = new TType(elementType);
2591 arrayType->makeArrays(arraySizes);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002592
Olli Etuaho13389b62016-10-16 11:48:18 +01002593 TIntermDeclaration *declaration = new TIntermDeclaration();
2594 declaration->setLine(identifierLocation);
2595
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002596 // initNode will correspond to the whole of "type b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002597 TIntermBinary *initNode = nullptr;
Olli Etuaho914b79a2017-06-19 16:03:19 +03002598 if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002599 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002600 if (initNode)
2601 {
2602 declaration->appendDeclarator(initNode);
2603 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002604 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002605
2606 return declaration;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002607}
2608
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002609TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
Martin Radev70866b82016-07-22 15:27:42 +03002610 const TTypeQualifierBuilder &typeQualifierBuilder,
2611 const TSourceLoc &identifierLoc,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002612 const ImmutableString &identifier,
Martin Radev70866b82016-07-22 15:27:42 +03002613 const TSymbol *symbol)
Jamie Madill47e3ec02014-08-20 16:38:33 -04002614{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002615 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002616
Martin Radev70866b82016-07-22 15:27:42 +03002617 if (!typeQualifier.invariant)
2618 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02002619 error(identifierLoc, "Expected invariant", identifier);
Martin Radev70866b82016-07-22 15:27:42 +03002620 return nullptr;
2621 }
2622 if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
2623 {
2624 return nullptr;
2625 }
Jamie Madill47e3ec02014-08-20 16:38:33 -04002626 if (!symbol)
2627 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02002628 error(identifierLoc, "undeclared identifier declared as invariant", identifier);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002629 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04002630 }
Martin Radev70866b82016-07-22 15:27:42 +03002631 if (!IsQualifierUnspecified(typeQualifier.qualifier))
Jamie Madill47e3ec02014-08-20 16:38:33 -04002632 {
Martin Radev70866b82016-07-22 15:27:42 +03002633 error(identifierLoc, "invariant declaration specifies qualifier",
2634 getQualifierString(typeQualifier.qualifier));
Jamie Madill47e3ec02014-08-20 16:38:33 -04002635 }
Martin Radev70866b82016-07-22 15:27:42 +03002636 if (typeQualifier.precision != EbpUndefined)
2637 {
2638 error(identifierLoc, "invariant declaration specifies precision",
2639 getPrecisionString(typeQualifier.precision));
2640 }
2641 if (!typeQualifier.layoutQualifier.isEmpty())
2642 {
2643 error(identifierLoc, "invariant declaration specifies layout", "'layout'");
2644 }
2645
2646 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
Olli Etuaho0f684632017-07-13 12:42:15 +03002647 if (!variable)
2648 {
2649 return nullptr;
2650 }
Martin Radev70866b82016-07-22 15:27:42 +03002651 const TType &type = variable->getType();
2652
2653 checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
2654 typeQualifier.line);
Olli Etuaho43364892017-02-13 16:00:12 +00002655 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev70866b82016-07-22 15:27:42 +03002656
Olli Etuaho76b2c382018-03-19 15:51:29 +02002657 symbolTable.addInvariantVarying(*variable);
Martin Radev70866b82016-07-22 15:27:42 +03002658
Olli Etuaho195be942017-12-04 23:40:14 +02002659 TIntermSymbol *intermSymbol = new TIntermSymbol(variable);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002660 intermSymbol->setLine(identifierLoc);
Martin Radev70866b82016-07-22 15:27:42 +03002661
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002662 return new TIntermInvariantDeclaration(intermSymbol, identifierLoc);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002663}
2664
Olli Etuaho13389b62016-10-16 11:48:18 +01002665void TParseContext::parseDeclarator(TPublicType &publicType,
2666 const TSourceLoc &identifierLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002667 const ImmutableString &identifier,
Olli Etuaho13389b62016-10-16 11:48:18 +01002668 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002669{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002670 // If the declaration starting this declarator list was empty (example: int,), some checks were
2671 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002672 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002673 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002674 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2675 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002676 }
2677
Olli Etuaho856c4972016-08-08 11:38:39 +03002678 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002679
Olli Etuahob60d30f2018-01-16 12:31:06 +02002680 TType *type = new TType(publicType);
Olli Etuaho454c34c2017-10-25 16:35:56 +03002681
Olli Etuahofbb1c792018-01-19 16:26:59 +02002682 checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, type);
Olli Etuaho454c34c2017-10-25 16:35:56 +03002683
Olli Etuahob60d30f2018-01-16 12:31:06 +02002684 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, type);
Olli Etuaho55bde912017-10-25 13:41:13 +03002685
Enrico Galliee7ffd92018-12-13 14:07:52 -08002686 if (IsAtomicCounter(type->getBasicType()))
2687 {
2688 checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, type);
2689
2690 checkAtomicCounterOffsetAlignment(identifierLocation, *type);
2691 }
Olli Etuaho55bc9052017-10-25 17:33:06 +03002692
Olli Etuaho195be942017-12-04 23:40:14 +02002693 TVariable *variable = nullptr;
2694 if (declareVariable(identifierLocation, identifier, type, &variable))
Olli Etuaho13389b62016-10-16 11:48:18 +01002695 {
Olli Etuaho195be942017-12-04 23:40:14 +02002696 TIntermSymbol *symbol = new TIntermSymbol(variable);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002697 symbol->setLine(identifierLocation);
Olli Etuaho13389b62016-10-16 11:48:18 +01002698 declarationOut->appendDeclarator(symbol);
2699 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002700}
2701
Olli Etuaho55bde912017-10-25 13:41:13 +03002702void TParseContext::parseArrayDeclarator(TPublicType &elementType,
Olli Etuaho13389b62016-10-16 11:48:18 +01002703 const TSourceLoc &identifierLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002704 const ImmutableString &identifier,
Olli Etuaho13389b62016-10-16 11:48:18 +01002705 const TSourceLoc &arrayLocation,
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002706 const TVector<unsigned int> &arraySizes,
Olli Etuaho13389b62016-10-16 11:48:18 +01002707 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002708{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002709 // If the declaration starting this declarator list was empty (example: int,), some checks were
2710 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002711 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002712 {
Olli Etuaho55bde912017-10-25 13:41:13 +03002713 nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002714 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002715 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002716
Olli Etuaho55bde912017-10-25 13:41:13 +03002717 checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002718
Olli Etuaho55bde912017-10-25 13:41:13 +03002719 if (checkIsValidTypeAndQualifierForArray(arrayLocation, elementType))
Jamie Madill502d66f2013-06-20 11:55:52 -04002720 {
Olli Etuahob60d30f2018-01-16 12:31:06 +02002721 TType *arrayType = new TType(elementType);
2722 arrayType->makeArrays(arraySizes);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002723
Olli Etuahofbb1c792018-01-19 16:26:59 +02002724 checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, arrayType);
Olli Etuaho454c34c2017-10-25 16:35:56 +03002725
Olli Etuahob60d30f2018-01-16 12:31:06 +02002726 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, arrayType);
Olli Etuaho55bde912017-10-25 13:41:13 +03002727
Enrico Galliee7ffd92018-12-13 14:07:52 -08002728 if (IsAtomicCounter(arrayType->getBasicType()))
2729 {
2730 checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, arrayType);
2731
2732 checkAtomicCounterOffsetAlignment(identifierLocation, *arrayType);
2733 }
jchen104cdac9e2017-05-08 11:01:20 +08002734
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002735 TVariable *variable = nullptr;
Olli Etuaho195be942017-12-04 23:40:14 +02002736 if (declareVariable(identifierLocation, identifier, arrayType, &variable))
Olli Etuahod7ceaa12017-07-12 17:46:35 +03002737 {
Olli Etuaho195be942017-12-04 23:40:14 +02002738 TIntermSymbol *symbol = new TIntermSymbol(variable);
Olli Etuahod7ceaa12017-07-12 17:46:35 +03002739 symbol->setLine(identifierLocation);
2740 declarationOut->appendDeclarator(symbol);
2741 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002742 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002743}
2744
Olli Etuaho13389b62016-10-16 11:48:18 +01002745void TParseContext::parseInitDeclarator(const TPublicType &publicType,
2746 const TSourceLoc &identifierLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002747 const ImmutableString &identifier,
Olli Etuaho13389b62016-10-16 11:48:18 +01002748 const TSourceLoc &initLocation,
2749 TIntermTyped *initializer,
2750 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002751{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002752 // If the declaration starting this declarator list was empty (example: int,), some checks were
2753 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002754 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002755 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002756 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2757 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002758 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002759
Olli Etuaho856c4972016-08-08 11:38:39 +03002760 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002761
Olli Etuaho13389b62016-10-16 11:48:18 +01002762 TIntermBinary *initNode = nullptr;
Olli Etuahob60d30f2018-01-16 12:31:06 +02002763 TType *type = new TType(publicType);
Olli Etuaho55bde912017-10-25 13:41:13 +03002764 if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04002765 {
2766 //
2767 // build the intermediate representation
2768 //
Olli Etuaho13389b62016-10-16 11:48:18 +01002769 if (initNode)
Jamie Madill502d66f2013-06-20 11:55:52 -04002770 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002771 declarationOut->appendDeclarator(initNode);
Jamie Madill502d66f2013-06-20 11:55:52 -04002772 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002773 }
2774}
2775
Olli Etuaho55bde912017-10-25 13:41:13 +03002776void TParseContext::parseArrayInitDeclarator(const TPublicType &elementType,
Olli Etuaho13389b62016-10-16 11:48:18 +01002777 const TSourceLoc &identifierLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002778 const ImmutableString &identifier,
Olli Etuaho13389b62016-10-16 11:48:18 +01002779 const TSourceLoc &indexLocation,
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002780 const TVector<unsigned int> &arraySizes,
Olli Etuaho13389b62016-10-16 11:48:18 +01002781 const TSourceLoc &initLocation,
2782 TIntermTyped *initializer,
2783 TIntermDeclaration *declarationOut)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002784{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002785 // If the declaration starting this declarator list was empty (example: int,), some checks were
2786 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002787 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002788 {
Olli Etuaho55bde912017-10-25 13:41:13 +03002789 nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002790 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002791 }
2792
Olli Etuaho55bde912017-10-25 13:41:13 +03002793 checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002794
Olli Etuaho55bde912017-10-25 13:41:13 +03002795 checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002796
Olli Etuahob60d30f2018-01-16 12:31:06 +02002797 TType *arrayType = new TType(elementType);
2798 arrayType->makeArrays(arraySizes);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002799
2800 // initNode will correspond to the whole of "b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002801 TIntermBinary *initNode = nullptr;
Olli Etuaho914b79a2017-06-19 16:03:19 +03002802 if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002803 {
2804 if (initNode)
2805 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002806 declarationOut->appendDeclarator(initNode);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002807 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002808 }
2809}
2810
Olli Etuahob8ee9dd2017-10-30 12:43:27 +02002811TIntermNode *TParseContext::addEmptyStatement(const TSourceLoc &location)
2812{
2813 // It's simpler to parse an empty statement as a constant expression rather than having a
2814 // different type of node just for empty statements, that will be pruned from the AST anyway.
2815 TIntermNode *node = CreateZeroNode(TType(EbtInt, EbpMedium));
2816 node->setLine(location);
2817 return node;
2818}
2819
jchen104cdac9e2017-05-08 11:01:20 +08002820void TParseContext::setAtomicCounterBindingDefaultOffset(const TPublicType &publicType,
2821 const TSourceLoc &location)
2822{
2823 const TLayoutQualifier &layoutQualifier = publicType.layoutQualifier;
2824 checkAtomicCounterBindingIsValid(location, layoutQualifier.binding);
2825 if (layoutQualifier.binding == -1 || layoutQualifier.offset == -1)
2826 {
2827 error(location, "Requires both binding and offset", "layout");
2828 return;
2829 }
2830 mAtomicCounterBindingStates[layoutQualifier.binding].setDefaultOffset(layoutQualifier.offset);
2831}
2832
Olli Etuahocce89652017-06-19 16:04:09 +03002833void TParseContext::parseDefaultPrecisionQualifier(const TPrecision precision,
2834 const TPublicType &type,
2835 const TSourceLoc &loc)
2836{
2837 if ((precision == EbpHigh) && (getShaderType() == GL_FRAGMENT_SHADER) &&
2838 !getFragmentPrecisionHigh())
2839 {
2840 error(loc, "precision is not supported in fragment shader", "highp");
2841 }
2842
2843 if (!CanSetDefaultPrecisionOnType(type))
2844 {
2845 error(loc, "illegal type argument for default precision qualifier",
2846 getBasicString(type.getBasicType()));
2847 return;
2848 }
2849 symbolTable.setDefaultPrecision(type.getBasicType(), precision);
2850}
2851
Shaob5cc1192017-07-06 10:47:20 +08002852bool TParseContext::checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier)
2853{
2854 switch (typeQualifier.layoutQualifier.primitiveType)
2855 {
2856 case EptLines:
2857 case EptLinesAdjacency:
2858 case EptTriangles:
2859 case EptTrianglesAdjacency:
2860 return typeQualifier.qualifier == EvqGeometryIn;
2861
2862 case EptLineStrip:
2863 case EptTriangleStrip:
2864 return typeQualifier.qualifier == EvqGeometryOut;
2865
2866 case EptPoints:
2867 return true;
2868
2869 default:
2870 UNREACHABLE();
2871 return false;
2872 }
2873}
2874
Jiawei Shao8e4b3552017-08-30 14:20:58 +08002875void TParseContext::setGeometryShaderInputArraySize(unsigned int inputArraySize,
2876 const TSourceLoc &line)
Jiawei Shaod8105a02017-08-08 09:54:36 +08002877{
Olli Etuaho94bbed12018-03-20 14:44:53 +02002878 if (!symbolTable.setGlInArraySize(inputArraySize))
Jiawei Shao8e4b3552017-08-30 14:20:58 +08002879 {
2880 error(line,
2881 "Array size or input primitive declaration doesn't match the size of earlier sized "
2882 "array inputs.",
2883 "layout");
2884 }
Jiawei Shaod8105a02017-08-08 09:54:36 +08002885}
2886
Shaob5cc1192017-07-06 10:47:20 +08002887bool TParseContext::parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier)
2888{
2889 ASSERT(typeQualifier.qualifier == EvqGeometryIn);
2890
2891 const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
2892
2893 if (layoutQualifier.maxVertices != -1)
2894 {
2895 error(typeQualifier.line,
2896 "max_vertices can only be declared in 'out' layout in a geometry shader", "layout");
2897 return false;
2898 }
2899
2900 // Set mGeometryInputPrimitiveType if exists
2901 if (layoutQualifier.primitiveType != EptUndefined)
2902 {
2903 if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier))
2904 {
2905 error(typeQualifier.line, "invalid primitive type for 'in' layout", "layout");
2906 return false;
2907 }
2908
2909 if (mGeometryShaderInputPrimitiveType == EptUndefined)
2910 {
2911 mGeometryShaderInputPrimitiveType = layoutQualifier.primitiveType;
Jiawei Shao8e4b3552017-08-30 14:20:58 +08002912 setGeometryShaderInputArraySize(
2913 GetGeometryShaderInputArraySize(mGeometryShaderInputPrimitiveType),
2914 typeQualifier.line);
Shaob5cc1192017-07-06 10:47:20 +08002915 }
2916 else if (mGeometryShaderInputPrimitiveType != layoutQualifier.primitiveType)
2917 {
2918 error(typeQualifier.line, "primitive doesn't match earlier input primitive declaration",
2919 "layout");
2920 return false;
2921 }
2922 }
2923
2924 // Set mGeometryInvocations if exists
2925 if (layoutQualifier.invocations > 0)
2926 {
2927 if (mGeometryShaderInvocations == 0)
2928 {
2929 mGeometryShaderInvocations = layoutQualifier.invocations;
2930 }
2931 else if (mGeometryShaderInvocations != layoutQualifier.invocations)
2932 {
2933 error(typeQualifier.line, "invocations contradicts to the earlier declaration",
2934 "layout");
2935 return false;
2936 }
2937 }
2938
2939 return true;
2940}
2941
2942bool TParseContext::parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier)
2943{
2944 ASSERT(typeQualifier.qualifier == EvqGeometryOut);
2945
2946 const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
2947
2948 if (layoutQualifier.invocations > 0)
2949 {
2950 error(typeQualifier.line,
2951 "invocations can only be declared in 'in' layout in a geometry shader", "layout");
2952 return false;
2953 }
2954
2955 // Set mGeometryOutputPrimitiveType if exists
2956 if (layoutQualifier.primitiveType != EptUndefined)
2957 {
2958 if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier))
2959 {
2960 error(typeQualifier.line, "invalid primitive type for 'out' layout", "layout");
2961 return false;
2962 }
2963
2964 if (mGeometryShaderOutputPrimitiveType == EptUndefined)
2965 {
2966 mGeometryShaderOutputPrimitiveType = layoutQualifier.primitiveType;
2967 }
2968 else if (mGeometryShaderOutputPrimitiveType != layoutQualifier.primitiveType)
2969 {
2970 error(typeQualifier.line,
2971 "primitive doesn't match earlier output primitive declaration", "layout");
2972 return false;
2973 }
2974 }
2975
2976 // Set mGeometryMaxVertices if exists
2977 if (layoutQualifier.maxVertices > -1)
2978 {
2979 if (mGeometryShaderMaxVertices == -1)
2980 {
2981 mGeometryShaderMaxVertices = layoutQualifier.maxVertices;
2982 }
2983 else if (mGeometryShaderMaxVertices != layoutQualifier.maxVertices)
2984 {
2985 error(typeQualifier.line, "max_vertices contradicts to the earlier declaration",
2986 "layout");
2987 return false;
2988 }
2989 }
2990
2991 return true;
2992}
2993
Martin Radev70866b82016-07-22 15:27:42 +03002994void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
Jamie Madilla295edf2013-06-06 11:56:48 -04002995{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002996 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madilla295edf2013-06-06 11:56:48 -04002997 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04002998
Martin Radev70866b82016-07-22 15:27:42 +03002999 checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
3000 typeQualifier.line);
3001
Jamie Madillc2128ff2016-07-04 10:26:17 -04003002 // It should never be the case, but some strange parser errors can send us here.
3003 if (layoutQualifier.isEmpty())
3004 {
3005 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04003006 return;
3007 }
Jamie Madilla295edf2013-06-06 11:56:48 -04003008
Martin Radev802abe02016-08-04 17:48:32 +03003009 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04003010 {
Olli Etuaho43364892017-02-13 16:00:12 +00003011 error(typeQualifier.line, "invalid layout qualifier combination", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04003012 return;
3013 }
3014
Olli Etuahoa78092c2018-09-26 14:16:13 +03003015 checkIndexIsNotSpecified(typeQualifier.line, layoutQualifier.index);
3016
Olli Etuaho43364892017-02-13 16:00:12 +00003017 checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);
3018
3019 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev2cc85b32016-08-05 16:22:53 +03003020
3021 checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
3022
Andrei Volykhina5527072017-03-22 16:46:30 +03003023 checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv);
3024
jchen104cdac9e2017-05-08 11:01:20 +08003025 checkOffsetIsNotSpecified(typeQualifier.line, layoutQualifier.offset);
3026
Qin Jiajiaca68d982017-09-18 16:41:56 +08003027 checkStd430IsForShaderStorageBlock(typeQualifier.line, layoutQualifier.blockStorage,
3028 typeQualifier.qualifier);
3029
Martin Radev802abe02016-08-04 17:48:32 +03003030 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04003031 {
Martin Radev802abe02016-08-04 17:48:32 +03003032 if (mComputeShaderLocalSizeDeclared &&
3033 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
3034 {
3035 error(typeQualifier.line, "Work group size does not match the previous declaration",
3036 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03003037 return;
3038 }
Jamie Madilla295edf2013-06-06 11:56:48 -04003039
Martin Radev802abe02016-08-04 17:48:32 +03003040 if (mShaderVersion < 310)
3041 {
3042 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03003043 return;
3044 }
Jamie Madill099c0f32013-06-20 11:55:52 -04003045
Martin Radev4c4c8e72016-08-04 12:25:34 +03003046 if (!layoutQualifier.localSize.isAnyValueSet())
Martin Radev802abe02016-08-04 17:48:32 +03003047 {
3048 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03003049 return;
3050 }
3051
3052 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
Olli Etuahofbb1c792018-01-19 16:26:59 +02003053 symbolTable.findBuiltIn(ImmutableString("gl_MaxComputeWorkGroupSize"), mShaderVersion));
Martin Radev802abe02016-08-04 17:48:32 +03003054
3055 const TConstantUnion *maxComputeWorkGroupSizeData =
3056 maxComputeWorkGroupSize->getConstPointer();
3057
3058 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
3059 {
3060 if (layoutQualifier.localSize[i] != -1)
3061 {
3062 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
3063 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
3064 if (mComputeShaderLocalSize[i] < 1 ||
3065 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
3066 {
Jonah Ryan-Davisf563fdc2019-01-31 13:53:59 -05003067 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
Olli Etuaho4de340a2016-12-16 09:32:03 +00003068 reasonStream << "invalid value: Value must be at least 1 and no greater than "
3069 << maxComputeWorkGroupSizeValue;
3070 const std::string &reason = reasonStream.str();
Martin Radev802abe02016-08-04 17:48:32 +03003071
Olli Etuaho4de340a2016-12-16 09:32:03 +00003072 error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03003073 return;
3074 }
3075 }
3076 }
3077
3078 mComputeShaderLocalSizeDeclared = true;
3079 }
Shaob5cc1192017-07-06 10:47:20 +08003080 else if (typeQualifier.qualifier == EvqGeometryIn)
3081 {
3082 if (mShaderVersion < 310)
3083 {
3084 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
3085 return;
3086 }
3087
3088 if (!parseGeometryShaderInputLayoutQualifier(typeQualifier))
3089 {
3090 return;
3091 }
3092 }
3093 else if (typeQualifier.qualifier == EvqGeometryOut)
3094 {
3095 if (mShaderVersion < 310)
3096 {
3097 error(typeQualifier.line, "out type qualifier supported in GLSL ES 3.10 only",
3098 "layout");
3099 return;
3100 }
3101
3102 if (!parseGeometryShaderOutputLayoutQualifier(typeQualifier))
3103 {
3104 return;
3105 }
3106 }
Mingyu Hu7d64c482019-03-12 14:27:40 -07003107 else if (isExtensionEnabled(TExtension::OVR_multiview2) &&
Olli Etuaho2a1e8f92017-07-14 11:49:36 +03003108 typeQualifier.qualifier == EvqVertexIn)
Olli Etuaho09b04a22016-12-15 13:30:26 +00003109 {
3110 // This error is only specified in WebGL, but tightens unspecified behavior in the native
3111 // specification.
3112 if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
3113 {
3114 error(typeQualifier.line, "Number of views does not match the previous declaration",
3115 "layout");
3116 return;
3117 }
3118
3119 if (layoutQualifier.numViews == -1)
3120 {
3121 error(typeQualifier.line, "No num_views specified", "layout");
3122 return;
3123 }
3124
3125 if (layoutQualifier.numViews > mMaxNumViews)
3126 {
3127 error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
3128 "layout");
3129 return;
3130 }
3131
3132 mNumViews = layoutQualifier.numViews;
3133 }
Martin Radev802abe02016-08-04 17:48:32 +03003134 else
Jamie Madill1566ef72013-06-20 11:55:54 -04003135 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00003136 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03003137 {
Martin Radev802abe02016-08-04 17:48:32 +03003138 return;
3139 }
3140
Jiajia Qinbc585152017-06-23 15:42:17 +08003141 if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer)
Martin Radev802abe02016-08-04 17:48:32 +03003142 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003143 error(typeQualifier.line, "invalid qualifier: global layout can only be set for blocks",
Olli Etuaho4de340a2016-12-16 09:32:03 +00003144 getQualifierString(typeQualifier.qualifier));
Martin Radev802abe02016-08-04 17:48:32 +03003145 return;
3146 }
3147
3148 if (mShaderVersion < 300)
3149 {
3150 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
3151 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03003152 return;
3153 }
3154
Olli Etuaho09b04a22016-12-15 13:30:26 +00003155 checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003156
3157 if (layoutQualifier.matrixPacking != EmpUnspecified)
3158 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003159 if (typeQualifier.qualifier == EvqUniform)
3160 {
3161 mDefaultUniformMatrixPacking = layoutQualifier.matrixPacking;
3162 }
3163 else if (typeQualifier.qualifier == EvqBuffer)
3164 {
3165 mDefaultBufferMatrixPacking = layoutQualifier.matrixPacking;
3166 }
Martin Radev802abe02016-08-04 17:48:32 +03003167 }
3168
3169 if (layoutQualifier.blockStorage != EbsUnspecified)
3170 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003171 if (typeQualifier.qualifier == EvqUniform)
3172 {
3173 mDefaultUniformBlockStorage = layoutQualifier.blockStorage;
3174 }
3175 else if (typeQualifier.qualifier == EvqBuffer)
3176 {
3177 mDefaultBufferBlockStorage = layoutQualifier.blockStorage;
3178 }
Martin Radev802abe02016-08-04 17:48:32 +03003179 }
Jamie Madill1566ef72013-06-20 11:55:54 -04003180 }
Jamie Madilla295edf2013-06-06 11:56:48 -04003181}
3182
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003183TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
3184 const TFunction &function,
3185 const TSourceLoc &location,
3186 bool insertParametersToSymbolTable)
3187{
Olli Etuahobed35d72017-12-20 16:36:26 +02003188 checkIsNotReserved(location, function.name());
Olli Etuahod7cd4ae2017-07-06 15:52:49 +03003189
Olli Etuahobeb6dc72017-12-14 16:03:03 +02003190 TIntermFunctionPrototype *prototype = new TIntermFunctionPrototype(&function);
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003191 prototype->setLine(location);
3192
3193 for (size_t i = 0; i < function.getParamCount(); i++)
3194 {
Olli Etuahod4bd9632018-03-08 16:32:44 +02003195 const TVariable *param = function.getParam(i);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003196
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003197 // If the parameter has no name, it's not an error, just don't add it to symbol table (could
3198 // be used for unused args).
Olli Etuahod4bd9632018-03-08 16:32:44 +02003199 if (param->symbolType() != SymbolType::Empty)
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003200 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003201 if (insertParametersToSymbolTable)
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003202 {
Olli Etuahod4bd9632018-03-08 16:32:44 +02003203 if (!symbolTable.declare(const_cast<TVariable *>(param)))
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003204 {
Olli Etuahod4bd9632018-03-08 16:32:44 +02003205 error(location, "redefinition", param->name());
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003206 }
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003207 }
Olli Etuaho55bde912017-10-25 13:41:13 +03003208 // Unsized type of a named parameter should have already been checked and sanitized.
Olli Etuahod4bd9632018-03-08 16:32:44 +02003209 ASSERT(!param->getType().isUnsizedArray());
Olli Etuaho55bde912017-10-25 13:41:13 +03003210 }
3211 else
3212 {
Olli Etuahod4bd9632018-03-08 16:32:44 +02003213 if (param->getType().isUnsizedArray())
Olli Etuaho55bde912017-10-25 13:41:13 +03003214 {
3215 error(location, "function parameter array must be sized at compile time", "[]");
3216 // We don't need to size the arrays since the parameter is unnamed and hence
3217 // inaccessible.
3218 }
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003219 }
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003220 }
3221 return prototype;
3222}
3223
Olli Etuaho16c745a2017-01-16 17:02:27 +00003224TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
3225 const TFunction &parsedFunction,
3226 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003227{
Olli Etuaho476197f2016-10-11 13:59:08 +01003228 // Note: function found from the symbol table could be the same as parsedFunction if this is the
3229 // first declaration. Either way the instance in the symbol table is used to track whether the
3230 // function is declared multiple times.
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003231 bool hadPrototypeDeclaration = false;
Olli Etuaho7c8567a2018-02-20 15:44:07 +02003232 const TFunction *function = symbolTable.markFunctionHasPrototypeDeclaration(
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003233 parsedFunction.getMangledName(), &hadPrototypeDeclaration);
3234
3235 if (hadPrototypeDeclaration && mShaderVersion == 100)
Olli Etuaho5d653182016-01-04 14:43:28 +02003236 {
3237 // ESSL 1.00.17 section 4.2.7.
3238 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
3239 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02003240 }
Olli Etuaho5d653182016-01-04 14:43:28 +02003241
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003242 TIntermFunctionPrototype *prototype =
3243 createPrototypeNodeFromFunction(*function, location, false);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003244
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003245 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02003246
3247 if (!symbolTable.atGlobalLevel())
3248 {
3249 // ESSL 3.00.4 section 4.2.4.
3250 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02003251 }
3252
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003253 return prototype;
3254}
3255
Olli Etuaho336b1472016-10-05 16:37:55 +01003256TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003257 TIntermFunctionPrototype *functionPrototype,
Olli Etuaho336b1472016-10-05 16:37:55 +01003258 TIntermBlock *functionBody,
3259 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003260{
Olli Etuahof51fdd22016-10-03 10:03:40 +01003261 // Check that non-void functions have at least one return statement.
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003262 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
3263 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02003264 error(location,
3265 "function does not return a value:", functionPrototype->getFunction()->name());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003266 }
3267
Olli Etuahof51fdd22016-10-03 10:03:40 +01003268 if (functionBody == nullptr)
3269 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01003270 functionBody = new TIntermBlock();
Olli Etuahof51fdd22016-10-03 10:03:40 +01003271 functionBody->setLine(location);
3272 }
Olli Etuaho336b1472016-10-05 16:37:55 +01003273 TIntermFunctionDefinition *functionNode =
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003274 new TIntermFunctionDefinition(functionPrototype, functionBody);
Olli Etuaho336b1472016-10-05 16:37:55 +01003275 functionNode->setLine(location);
Olli Etuahof51fdd22016-10-03 10:03:40 +01003276
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003277 symbolTable.pop();
Olli Etuahof51fdd22016-10-03 10:03:40 +01003278 return functionNode;
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003279}
3280
Olli Etuaho476197f2016-10-11 13:59:08 +01003281void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003282 const TFunction *function,
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003283 TIntermFunctionPrototype **prototypeOut)
Jamie Madill185fb402015-06-12 15:48:48 -04003284{
Olli Etuaho476197f2016-10-11 13:59:08 +01003285 ASSERT(function);
Jamie Madill185fb402015-06-12 15:48:48 -04003286
Olli Etuaho7c8567a2018-02-20 15:44:07 +02003287 bool wasDefined = false;
3288 function = symbolTable.setFunctionParameterNamesFromDefinition(function, &wasDefined);
3289 if (wasDefined)
Jamie Madill185fb402015-06-12 15:48:48 -04003290 {
Olli Etuaho7c8567a2018-02-20 15:44:07 +02003291 error(location, "function already has a body", function->name());
Jamie Madill185fb402015-06-12 15:48:48 -04003292 }
Jamie Madill185fb402015-06-12 15:48:48 -04003293
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003294 // Remember the return type for later checking for return statements.
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003295 mCurrentFunctionType = &(function->getReturnType());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003296 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04003297
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003298 *prototypeOut = createPrototypeNodeFromFunction(*function, location, true);
Jamie Madill185fb402015-06-12 15:48:48 -04003299 setLoopNestingLevel(0);
3300}
3301
Jamie Madillb98c3a82015-07-23 14:26:04 -04003302TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04003303{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00003304 //
Olli Etuaho5d653182016-01-04 14:43:28 +02003305 // We don't know at this point whether this is a function definition or a prototype.
3306 // The definition production code will check for redefinitions.
3307 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00003308 //
Olli Etuahoc4a96d62015-07-23 17:37:39 +05303309
Olli Etuahod80f2942017-11-06 12:44:45 +02003310 for (size_t i = 0u; i < function->getParamCount(); ++i)
3311 {
Olli Etuahod4bd9632018-03-08 16:32:44 +02003312 const TVariable *param = function->getParam(i);
3313 if (param->getType().isStructSpecifier())
Olli Etuahod80f2942017-11-06 12:44:45 +02003314 {
3315 // ESSL 3.00.6 section 12.10.
3316 error(location, "Function parameter type cannot be a structure definition",
Olli Etuahofbb1c792018-01-19 16:26:59 +02003317 function->name());
Olli Etuahod80f2942017-11-06 12:44:45 +02003318 }
3319 }
3320
Olli Etuaho7c8567a2018-02-20 15:44:07 +02003321 if (getShaderVersion() >= 300)
Olli Etuahoc4a96d62015-07-23 17:37:39 +05303322 {
Olli Etuaho7c8567a2018-02-20 15:44:07 +02003323 const UnmangledBuiltIn *builtIn =
3324 symbolTable.getUnmangledBuiltInForShaderVersion(function->name(), getShaderVersion());
3325 if (builtIn &&
3326 (builtIn->extension == TExtension::UNDEFINED || isExtensionEnabled(builtIn->extension)))
3327 {
3328 // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as
3329 // functions. Therefore overloading or redefining builtin functions is an error.
3330 error(location, "Name of a built-in function cannot be redeclared as function",
3331 function->name());
3332 }
Olli Etuahoc4a96d62015-07-23 17:37:39 +05303333 }
Olli Etuaho7c8567a2018-02-20 15:44:07 +02003334 else
3335 {
3336 // ESSL 1.00.17 section 4.2.6: built-ins can be overloaded but not redefined. We assume that
3337 // this applies to redeclarations as well.
3338 const TSymbol *builtIn =
3339 symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
3340 if (builtIn)
3341 {
3342 error(location, "built-in functions cannot be redefined", function->name());
3343 }
3344 }
3345
3346 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
3347 // here.
3348 const TFunction *prevDec =
3349 static_cast<const TFunction *>(symbolTable.findGlobal(function->getMangledName()));
3350 if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04003351 {
3352 if (prevDec->getReturnType() != function->getReturnType())
3353 {
Olli Etuaho476197f2016-10-11 13:59:08 +01003354 error(location, "function must have the same return type in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04003355 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04003356 }
3357 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
3358 {
Olli Etuahod4bd9632018-03-08 16:32:44 +02003359 if (prevDec->getParam(i)->getType().getQualifier() !=
3360 function->getParam(i)->getType().getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04003361 {
Olli Etuaho476197f2016-10-11 13:59:08 +01003362 error(location,
3363 "function must have the same parameter qualifiers in all of its declarations",
Olli Etuahod4bd9632018-03-08 16:32:44 +02003364 function->getParam(i)->getType().getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04003365 }
3366 }
3367 }
3368
Jamie Madill185fb402015-06-12 15:48:48 -04003369 // Check for previously declared variables using the same name.
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003370 const TSymbol *prevSym = symbolTable.find(function->name(), getShaderVersion());
3371 bool insertUnmangledName = true;
Jamie Madill185fb402015-06-12 15:48:48 -04003372 if (prevSym)
3373 {
3374 if (!prevSym->isFunction())
3375 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02003376 error(location, "redefinition of a function", function->name());
Jamie Madill185fb402015-06-12 15:48:48 -04003377 }
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003378 insertUnmangledName = false;
Jamie Madill185fb402015-06-12 15:48:48 -04003379 }
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003380 // Parsing is at the inner scope level of the function's arguments and body statement at this
3381 // point, but declareUserDefinedFunction takes care of declaring the function at the global
3382 // scope.
3383 symbolTable.declareUserDefinedFunction(function, insertUnmangledName);
Jamie Madill185fb402015-06-12 15:48:48 -04003384
Olli Etuaho78d13742017-01-18 13:06:10 +00003385 // Raise error message if main function takes any parameters or return anything other than void
Olli Etuahofbb1c792018-01-19 16:26:59 +02003386 if (function->isMain())
Olli Etuaho78d13742017-01-18 13:06:10 +00003387 {
3388 if (function->getParamCount() > 0)
3389 {
3390 error(location, "function cannot take any parameter(s)", "main");
3391 }
3392 if (function->getReturnType().getBasicType() != EbtVoid)
3393 {
3394 error(location, "main function cannot return a value",
3395 function->getReturnType().getBasicString());
3396 }
3397 }
3398
Jamie Madill185fb402015-06-12 15:48:48 -04003399 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04003400 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
3401 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04003402 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
3403 //
3404 return function;
3405}
3406
Olli Etuaho9de84a52016-06-14 17:36:01 +03003407TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
Olli Etuahofbb1c792018-01-19 16:26:59 +02003408 const ImmutableString &name,
Olli Etuaho9de84a52016-06-14 17:36:01 +03003409 const TSourceLoc &location)
3410{
3411 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
3412 {
3413 error(location, "no qualifiers allowed for function return",
3414 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03003415 }
3416 if (!type.layoutQualifier.isEmpty())
3417 {
3418 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03003419 }
jchen10cc2a10e2017-05-03 14:05:12 +08003420 // make sure an opaque type is not involved as well...
3421 std::string reason(getBasicString(type.getBasicType()));
3422 reason += "s can't be function return values";
3423 checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03003424 if (mShaderVersion < 300)
3425 {
3426 // Array return values are forbidden, but there's also no valid syntax for declaring array
3427 // return values in ESSL 1.00.
Olli Etuaho7881cfd2017-08-23 18:00:21 +03003428 ASSERT(!type.isArray() || mDiagnostics->numErrors() > 0);
Olli Etuahoe29324f2016-06-15 10:58:03 +03003429
3430 if (type.isStructureContainingArrays())
3431 {
3432 // ESSL 1.00.17 section 6.1 Function Definitions
Olli Etuaho72e35892018-06-20 11:43:08 +03003433 TInfoSinkBase typeString;
3434 typeString << TType(type);
Olli Etuahoe29324f2016-06-15 10:58:03 +03003435 error(location, "structures containing arrays can't be function return values",
Olli Etuaho72e35892018-06-20 11:43:08 +03003436 typeString.c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03003437 }
3438 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03003439
3440 // Add the function as a prototype after parsing it (we do not support recursion)
Olli Etuaho029e8ca2018-02-16 14:06:49 +02003441 return new TFunction(&symbolTable, name, SymbolType::UserDefined, new TType(type), false);
Olli Etuaho9de84a52016-06-14 17:36:01 +03003442}
3443
Olli Etuaho697bf652018-02-16 11:50:54 +02003444TFunctionLookup *TParseContext::addNonConstructorFunc(const ImmutableString &name,
3445 const TSymbol *symbol)
Olli Etuahocce89652017-06-19 16:04:09 +03003446{
Olli Etuaho697bf652018-02-16 11:50:54 +02003447 return TFunctionLookup::CreateFunctionCall(name, symbol);
Olli Etuahocce89652017-06-19 16:04:09 +03003448}
3449
Olli Etuaho95ed1942018-02-01 14:01:19 +02003450TFunctionLookup *TParseContext::addConstructorFunc(const TPublicType &publicType)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00003451{
Olli Etuaho7881cfd2017-08-23 18:00:21 +03003452 if (mShaderVersion < 300 && publicType.isArray())
Olli Etuahocce89652017-06-19 16:04:09 +03003453 {
3454 error(publicType.getLine(), "array constructor supported in GLSL ES 3.00 and above only",
3455 "[]");
3456 }
Martin Radev4a9cd802016-09-01 16:51:51 +03003457 if (publicType.isStructSpecifier())
Olli Etuahobd163f62015-11-13 12:15:38 +02003458 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003459 error(publicType.getLine(), "constructor can't be a structure definition",
3460 getBasicString(publicType.getBasicType()));
Olli Etuahobd163f62015-11-13 12:15:38 +02003461 }
3462
Olli Etuahoa7ecec32017-05-08 17:43:55 +03003463 TType *type = new TType(publicType);
3464 if (!type->canBeConstructed())
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00003465 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03003466 error(publicType.getLine(), "cannot construct this type",
3467 getBasicString(publicType.getBasicType()));
3468 type->setBasicType(EbtFloat);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00003469 }
Olli Etuaho95ed1942018-02-01 14:01:19 +02003470 return TFunctionLookup::CreateConstructor(type);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00003471}
3472
Olli Etuaho55bde912017-10-25 13:41:13 +03003473void TParseContext::checkIsNotUnsizedArray(const TSourceLoc &line,
3474 const char *errorMessage,
Olli Etuahofbb1c792018-01-19 16:26:59 +02003475 const ImmutableString &token,
Olli Etuaho55bde912017-10-25 13:41:13 +03003476 TType *arrayType)
3477{
3478 if (arrayType->isUnsizedArray())
3479 {
3480 error(line, errorMessage, token);
Kai Ninomiya57ea5332017-11-22 14:04:48 -08003481 arrayType->sizeUnsizedArrays(nullptr);
Olli Etuaho55bde912017-10-25 13:41:13 +03003482 }
3483}
3484
3485TParameter TParseContext::parseParameterDeclarator(TType *type,
Olli Etuahofbb1c792018-01-19 16:26:59 +02003486 const ImmutableString &name,
Olli Etuahocce89652017-06-19 16:04:09 +03003487 const TSourceLoc &nameLoc)
3488{
Olli Etuaho55bde912017-10-25 13:41:13 +03003489 ASSERT(type);
Olli Etuahofbb1c792018-01-19 16:26:59 +02003490 checkIsNotUnsizedArray(nameLoc, "function parameter array must specify a size", name, type);
Olli Etuaho55bde912017-10-25 13:41:13 +03003491 if (type->getBasicType() == EbtVoid)
Olli Etuahocce89652017-06-19 16:04:09 +03003492 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02003493 error(nameLoc, "illegal use of type 'void'", name);
Olli Etuahocce89652017-06-19 16:04:09 +03003494 }
Olli Etuahofbb1c792018-01-19 16:26:59 +02003495 checkIsNotReserved(nameLoc, name);
3496 TParameter param = {name.data(), type};
Olli Etuahocce89652017-06-19 16:04:09 +03003497 return param;
3498}
3499
Olli Etuaho55bde912017-10-25 13:41:13 +03003500TParameter TParseContext::parseParameterDeclarator(const TPublicType &publicType,
Olli Etuahofbb1c792018-01-19 16:26:59 +02003501 const ImmutableString &name,
Olli Etuaho55bde912017-10-25 13:41:13 +03003502 const TSourceLoc &nameLoc)
Olli Etuahocce89652017-06-19 16:04:09 +03003503{
Olli Etuaho55bde912017-10-25 13:41:13 +03003504 TType *type = new TType(publicType);
3505 return parseParameterDeclarator(type, name, nameLoc);
3506}
3507
Olli Etuahofbb1c792018-01-19 16:26:59 +02003508TParameter TParseContext::parseParameterArrayDeclarator(const ImmutableString &name,
Olli Etuaho55bde912017-10-25 13:41:13 +03003509 const TSourceLoc &nameLoc,
Olli Etuaho7881cfd2017-08-23 18:00:21 +03003510 const TVector<unsigned int> &arraySizes,
Olli Etuaho55bde912017-10-25 13:41:13 +03003511 const TSourceLoc &arrayLoc,
3512 TPublicType *elementType)
3513{
3514 checkArrayElementIsNotArray(arrayLoc, *elementType);
3515 TType *arrayType = new TType(*elementType);
Olli Etuaho7881cfd2017-08-23 18:00:21 +03003516 arrayType->makeArrays(arraySizes);
Olli Etuaho55bde912017-10-25 13:41:13 +03003517 return parseParameterDeclarator(arrayType, name, nameLoc);
Olli Etuahocce89652017-06-19 16:04:09 +03003518}
3519
Olli Etuaho95ed1942018-02-01 14:01:19 +02003520bool TParseContext::checkUnsizedArrayConstructorArgumentDimensionality(
3521 const TIntermSequence &arguments,
3522 TType type,
3523 const TSourceLoc &line)
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003524{
Olli Etuaho95ed1942018-02-01 14:01:19 +02003525 if (arguments.empty())
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003526 {
3527 error(line, "implicitly sized array constructor must have at least one argument", "[]");
3528 return false;
3529 }
Olli Etuaho95ed1942018-02-01 14:01:19 +02003530 for (TIntermNode *arg : arguments)
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003531 {
Olli Etuaho95ed1942018-02-01 14:01:19 +02003532 const TIntermTyped *element = arg->getAsTyped();
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003533 ASSERT(element);
Kai Ninomiya57ea5332017-11-22 14:04:48 -08003534 size_t dimensionalityFromElement = element->getType().getNumArraySizes() + 1u;
3535 if (dimensionalityFromElement > type.getNumArraySizes())
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003536 {
3537 error(line, "constructing from a non-dereferenced array", "constructor");
3538 return false;
3539 }
Kai Ninomiya57ea5332017-11-22 14:04:48 -08003540 else if (dimensionalityFromElement < type.getNumArraySizes())
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003541 {
3542 if (dimensionalityFromElement == 1u)
3543 {
3544 error(line, "implicitly sized array of arrays constructor argument is not an array",
3545 "constructor");
3546 }
3547 else
3548 {
3549 error(line,
3550 "implicitly sized array of arrays constructor argument dimensionality is too "
3551 "low",
3552 "constructor");
3553 }
3554 return false;
3555 }
3556 }
3557 return true;
3558}
3559
Jamie Madillb98c3a82015-07-23 14:26:04 -04003560// This function is used to test for the correctness of the parameters passed to various constructor
3561// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003562//
Olli Etuaho856c4972016-08-08 11:38:39 +03003563// 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 +00003564//
Olli Etuaho95ed1942018-02-01 14:01:19 +02003565TIntermTyped *TParseContext::addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003566{
Olli Etuaho95ed1942018-02-01 14:01:19 +02003567 TType type = fnCall->constructorType();
3568 TIntermSequence &arguments = fnCall->arguments();
Olli Etuaho856c4972016-08-08 11:38:39 +03003569 if (type.isUnsizedArray())
3570 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003571 if (!checkUnsizedArrayConstructorArgumentDimensionality(arguments, type, line))
Olli Etuahobbe9fb52016-11-03 17:16:05 +00003572 {
Kai Ninomiya57ea5332017-11-22 14:04:48 -08003573 type.sizeUnsizedArrays(nullptr);
Olli Etuaho3ec75682017-07-05 17:02:55 +03003574 return CreateZeroNode(type);
Olli Etuahobbe9fb52016-11-03 17:16:05 +00003575 }
Olli Etuaho95ed1942018-02-01 14:01:19 +02003576 TIntermTyped *firstElement = arguments.at(0)->getAsTyped();
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003577 ASSERT(firstElement);
Olli Etuaho9cd71632017-10-26 14:43:20 +03003578 if (type.getOutermostArraySize() == 0u)
3579 {
Olli Etuaho95ed1942018-02-01 14:01:19 +02003580 type.sizeOutermostUnsizedArray(static_cast<unsigned int>(arguments.size()));
Olli Etuaho9cd71632017-10-26 14:43:20 +03003581 }
Kai Ninomiya57ea5332017-11-22 14:04:48 -08003582 for (size_t i = 0; i < firstElement->getType().getNumArraySizes(); ++i)
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003583 {
Kai Ninomiya57ea5332017-11-22 14:04:48 -08003584 if ((*type.getArraySizes())[i] == 0u)
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003585 {
Kai Ninomiya57ea5332017-11-22 14:04:48 -08003586 type.setArraySize(i, (*firstElement->getType().getArraySizes())[i]);
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003587 }
3588 }
3589 ASSERT(!type.isUnsizedArray());
Olli Etuaho856c4972016-08-08 11:38:39 +03003590 }
Olli Etuaho856c4972016-08-08 11:38:39 +03003591
Olli Etuahoa7ecec32017-05-08 17:43:55 +03003592 if (!checkConstructorArguments(line, arguments, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03003593 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03003594 return CreateZeroNode(type);
Olli Etuaho856c4972016-08-08 11:38:39 +03003595 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003596
Olli Etuaho95ed1942018-02-01 14:01:19 +02003597 TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, &arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08003598 constructorNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003599
Olli Etuaho765924f2018-01-04 12:48:36 +02003600 return constructorNode->fold(mDiagnostics);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003601}
3602
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003603//
3604// Interface/uniform blocks
Jiawei Shaobd924af2017-11-16 15:28:04 +08003605// TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003606//
Olli Etuaho13389b62016-10-16 11:48:18 +01003607TIntermDeclaration *TParseContext::addInterfaceBlock(
Martin Radev70866b82016-07-22 15:27:42 +03003608 const TTypeQualifierBuilder &typeQualifierBuilder,
3609 const TSourceLoc &nameLine,
Olli Etuahofbb1c792018-01-19 16:26:59 +02003610 const ImmutableString &blockName,
Martin Radev70866b82016-07-22 15:27:42 +03003611 TFieldList *fieldList,
Olli Etuahofbb1c792018-01-19 16:26:59 +02003612 const ImmutableString &instanceName,
Martin Radev70866b82016-07-22 15:27:42 +03003613 const TSourceLoc &instanceLine,
3614 TIntermTyped *arrayIndex,
3615 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003616{
Olli Etuaho856c4972016-08-08 11:38:39 +03003617 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003618
Olli Etuaho77ba4082016-12-16 12:01:18 +00003619 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03003620
Jiajia Qinbc585152017-06-23 15:42:17 +08003621 if (mShaderVersion < 310 && typeQualifier.qualifier != EvqUniform)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003622 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003623 error(typeQualifier.line,
3624 "invalid qualifier: interface blocks must be uniform in version lower than GLSL ES "
3625 "3.10",
3626 getQualifierString(typeQualifier.qualifier));
3627 }
3628 else if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer)
3629 {
3630 error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform or buffer",
Olli Etuaho4de340a2016-12-16 09:32:03 +00003631 getQualifierString(typeQualifier.qualifier));
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003632 }
3633
Martin Radev70866b82016-07-22 15:27:42 +03003634 if (typeQualifier.invariant)
3635 {
3636 error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
3637 }
3638
Jiajia Qinbc585152017-06-23 15:42:17 +08003639 if (typeQualifier.qualifier != EvqBuffer)
3640 {
3641 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
3642 }
Olli Etuaho43364892017-02-13 16:00:12 +00003643
jchen10af713a22017-04-19 09:10:56 +08003644 // add array index
3645 unsigned int arraySize = 0;
3646 if (arrayIndex != nullptr)
3647 {
3648 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
3649 }
3650
Olli Etuahoa78092c2018-09-26 14:16:13 +03003651 checkIndexIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.index);
3652
jchen10af713a22017-04-19 09:10:56 +08003653 if (mShaderVersion < 310)
3654 {
3655 checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
3656 }
3657 else
3658 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003659 checkBlockBindingIsValid(typeQualifier.line, typeQualifier.qualifier,
3660 typeQualifier.layoutQualifier.binding, arraySize);
jchen10af713a22017-04-19 09:10:56 +08003661 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003662
Andrei Volykhina5527072017-03-22 16:46:30 +03003663 checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
3664
Jamie Madill099c0f32013-06-20 11:55:52 -04003665 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03003666 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Qin Jiajiaca68d982017-09-18 16:41:56 +08003667 checkStd430IsForShaderStorageBlock(typeQualifier.line, blockLayoutQualifier.blockStorage,
3668 typeQualifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003669
Jamie Madill099c0f32013-06-20 11:55:52 -04003670 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
3671 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003672 if (typeQualifier.qualifier == EvqUniform)
3673 {
3674 blockLayoutQualifier.matrixPacking = mDefaultUniformMatrixPacking;
3675 }
3676 else if (typeQualifier.qualifier == EvqBuffer)
3677 {
3678 blockLayoutQualifier.matrixPacking = mDefaultBufferMatrixPacking;
3679 }
Jamie Madill099c0f32013-06-20 11:55:52 -04003680 }
3681
Jamie Madill1566ef72013-06-20 11:55:54 -04003682 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
3683 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003684 if (typeQualifier.qualifier == EvqUniform)
3685 {
3686 blockLayoutQualifier.blockStorage = mDefaultUniformBlockStorage;
3687 }
3688 else if (typeQualifier.qualifier == EvqBuffer)
3689 {
3690 blockLayoutQualifier.blockStorage = mDefaultBufferBlockStorage;
3691 }
Jamie Madill1566ef72013-06-20 11:55:54 -04003692 }
3693
Olli Etuaho856c4972016-08-08 11:38:39 +03003694 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003695
Martin Radev2cc85b32016-08-05 16:22:53 +03003696 checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
3697
Jamie Madill98493dd2013-07-08 14:39:03 -04003698 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05303699 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
3700 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003701 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05303702 TType *fieldType = field->type();
jchen10cc2a10e2017-05-03 14:05:12 +08003703 if (IsOpaqueType(fieldType->getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +05303704 {
jchen10cc2a10e2017-05-03 14:05:12 +08003705 std::string reason("unsupported type - ");
3706 reason += fieldType->getBasicString();
3707 reason += " types are not allowed in interface blocks";
3708 error(field->line(), reason.c_str(), fieldType->getBasicString());
Martin Radev2cc85b32016-08-05 16:22:53 +03003709 }
3710
Jamie Madill98493dd2013-07-08 14:39:03 -04003711 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003712 switch (qualifier)
3713 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003714 case EvqGlobal:
Jiajia Qinbc585152017-06-23 15:42:17 +08003715 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003716 case EvqUniform:
Jiajia Qinbc585152017-06-23 15:42:17 +08003717 if (typeQualifier.qualifier == EvqBuffer)
3718 {
3719 error(field->line(), "invalid qualifier on shader storage block member",
3720 getQualifierString(qualifier));
3721 }
3722 break;
3723 case EvqBuffer:
3724 if (typeQualifier.qualifier == EvqUniform)
3725 {
3726 error(field->line(), "invalid qualifier on uniform block member",
3727 getQualifierString(qualifier));
3728 }
Jamie Madillb98c3a82015-07-23 14:26:04 -04003729 break;
3730 default:
3731 error(field->line(), "invalid qualifier on interface block member",
3732 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003733 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003734 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003735
Martin Radev70866b82016-07-22 15:27:42 +03003736 if (fieldType->isInvariant())
3737 {
3738 error(field->line(), "invalid qualifier on interface block member", "invariant");
3739 }
3740
Jamie Madilla5efff92013-06-06 11:56:47 -04003741 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04003742 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03003743 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Olli Etuahoa78092c2018-09-26 14:16:13 +03003744 checkIndexIsNotSpecified(field->line(), fieldLayoutQualifier.index);
jchen10af713a22017-04-19 09:10:56 +08003745 checkBindingIsNotSpecified(field->line(), fieldLayoutQualifier.binding);
Jamie Madill099c0f32013-06-20 11:55:52 -04003746
Jamie Madill98493dd2013-07-08 14:39:03 -04003747 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04003748 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003749 error(field->line(), "invalid layout qualifier: cannot be used here",
3750 getBlockStorageString(fieldLayoutQualifier.blockStorage));
Jamie Madill1566ef72013-06-20 11:55:54 -04003751 }
3752
Jamie Madill98493dd2013-07-08 14:39:03 -04003753 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04003754 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003755 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04003756 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03003757 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04003758 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003759 warning(field->line(),
3760 "extraneous layout qualifier: only has an effect on matrix types",
3761 getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
Jamie Madill099c0f32013-06-20 11:55:52 -04003762 }
3763
Jamie Madill98493dd2013-07-08 14:39:03 -04003764 fieldType->setLayoutQualifier(fieldLayoutQualifier);
Jiajia Qinbc585152017-06-23 15:42:17 +08003765
Olli Etuahoebee5b32017-11-23 12:56:32 +02003766 if (mShaderVersion < 310 || memberIndex != fieldList->size() - 1u ||
3767 typeQualifier.qualifier != EvqBuffer)
3768 {
3769 // ESSL 3.10 spec section 4.1.9 allows for runtime-sized arrays.
3770 checkIsNotUnsizedArray(field->line(),
3771 "array members of interface blocks must specify a size",
Olli Etuahofbb1c792018-01-19 16:26:59 +02003772 field->name(), field->type());
Olli Etuahoebee5b32017-11-23 12:56:32 +02003773 }
3774
Jiajia Qinbc585152017-06-23 15:42:17 +08003775 if (typeQualifier.qualifier == EvqBuffer)
3776 {
3777 // set memory qualifiers
3778 // GLSL ES 3.10 session 4.9 [Memory Access Qualifiers]. When a block declaration is
3779 // qualified with a memory qualifier, it is as if all of its members were declared with
3780 // the same memory qualifier.
3781 const TMemoryQualifier &blockMemoryQualifier = typeQualifier.memoryQualifier;
3782 TMemoryQualifier fieldMemoryQualifier = fieldType->getMemoryQualifier();
3783 fieldMemoryQualifier.readonly |= blockMemoryQualifier.readonly;
3784 fieldMemoryQualifier.writeonly |= blockMemoryQualifier.writeonly;
3785 fieldMemoryQualifier.coherent |= blockMemoryQualifier.coherent;
3786 fieldMemoryQualifier.restrictQualifier |= blockMemoryQualifier.restrictQualifier;
3787 fieldMemoryQualifier.volatileQualifier |= blockMemoryQualifier.volatileQualifier;
3788 // TODO(jiajia.qin@intel.com): Decide whether if readonly and writeonly buffer variable
3789 // is legal. See bug https://github.com/KhronosGroup/OpenGL-API/issues/7
3790 fieldType->setMemoryQualifier(fieldMemoryQualifier);
3791 }
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003792 }
3793
Olli Etuaho9d4d7f02017-12-07 17:11:41 +01003794 TInterfaceBlock *interfaceBlock = new TInterfaceBlock(
Olli Etuahofbb1c792018-01-19 16:26:59 +02003795 &symbolTable, blockName, fieldList, blockLayoutQualifier, SymbolType::UserDefined);
Olli Etuaho437664b2018-02-28 15:38:14 +02003796 if (!symbolTable.declare(interfaceBlock))
Olli Etuaho378c3a52017-12-04 11:32:13 +02003797 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02003798 error(nameLine, "redefinition of an interface block name", blockName);
Olli Etuaho378c3a52017-12-04 11:32:13 +02003799 }
3800
Olli Etuahob60d30f2018-01-16 12:31:06 +02003801 TType *interfaceBlockType =
3802 new TType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier);
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003803 if (arrayIndex != nullptr)
3804 {
Olli Etuahob60d30f2018-01-16 12:31:06 +02003805 interfaceBlockType->makeArray(arraySize);
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003806 }
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003807
Olli Etuaho195be942017-12-04 23:40:14 +02003808 // The instance variable gets created to refer to the interface block type from the AST
Olli Etuahoae4dbf32017-12-08 20:49:00 +01003809 // regardless of if there's an instance name. It's created as an empty symbol if there is no
3810 // instance name.
Olli Etuaho195be942017-12-04 23:40:14 +02003811 TVariable *instanceVariable =
Olli Etuahoae4dbf32017-12-08 20:49:00 +01003812 new TVariable(&symbolTable, instanceName, interfaceBlockType,
Olli Etuahofbb1c792018-01-19 16:26:59 +02003813 instanceName.empty() ? SymbolType::Empty : SymbolType::UserDefined);
Olli Etuaho195be942017-12-04 23:40:14 +02003814
Olli Etuahoae4dbf32017-12-08 20:49:00 +01003815 if (instanceVariable->symbolType() == SymbolType::Empty)
Olli Etuaho195be942017-12-04 23:40:14 +02003816 {
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003817 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04003818 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
3819 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003820 TField *field = (*fieldList)[memberIndex];
Olli Etuahob60d30f2018-01-16 12:31:06 +02003821 TType *fieldType = new TType(*field->type());
Jamie Madill98493dd2013-07-08 14:39:03 -04003822
3823 // set parent pointer of the field variable
3824 fieldType->setInterfaceBlock(interfaceBlock);
3825
Olli Etuahob60d30f2018-01-16 12:31:06 +02003826 fieldType->setQualifier(typeQualifier.qualifier);
3827
Olli Etuaho195be942017-12-04 23:40:14 +02003828 TVariable *fieldVariable =
Olli Etuahofbb1c792018-01-19 16:26:59 +02003829 new TVariable(&symbolTable, field->name(), fieldType, SymbolType::UserDefined);
Olli Etuaho437664b2018-02-28 15:38:14 +02003830 if (!symbolTable.declare(fieldVariable))
Arun Patole7e7e68d2015-05-22 12:02:25 +05303831 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003832 error(field->line(), "redefinition of an interface block member name",
Olli Etuahofbb1c792018-01-19 16:26:59 +02003833 field->name());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003834 }
3835 }
3836 }
3837 else
3838 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02003839 checkIsNotReserved(instanceLine, instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03003840
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003841 // add a symbol for this interface block
Olli Etuaho437664b2018-02-28 15:38:14 +02003842 if (!symbolTable.declare(instanceVariable))
Arun Patole7e7e68d2015-05-22 12:02:25 +05303843 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02003844 error(instanceLine, "redefinition of an interface block instance name", instanceName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003845 }
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003846 }
3847
Olli Etuaho195be942017-12-04 23:40:14 +02003848 TIntermSymbol *blockSymbol = new TIntermSymbol(instanceVariable);
3849 blockSymbol->setLine(typeQualifier.line);
3850 TIntermDeclaration *declaration = new TIntermDeclaration();
3851 declaration->appendDeclarator(blockSymbol);
3852 declaration->setLine(nameLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04003853
3854 exitStructDeclaration();
Olli Etuaho13389b62016-10-16 11:48:18 +01003855 return declaration;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003856}
3857
Olli Etuahofbb1c792018-01-19 16:26:59 +02003858void TParseContext::enterStructDeclaration(const TSourceLoc &line,
3859 const ImmutableString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00003860{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003861 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003862
3863 // Embedded structure definitions are not supported per GLSL ES spec.
Olli Etuaho4de340a2016-12-16 09:32:03 +00003864 // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
Arun Patole7e7e68d2015-05-22 12:02:25 +05303865 if (mStructNestingLevel > 1)
3866 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003867 error(line, "Embedded struct definitions are not allowed", "struct");
kbr@chromium.org476541f2011-10-27 21:14:51 +00003868 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00003869}
3870
3871void TParseContext::exitStructDeclaration()
3872{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003873 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003874}
3875
Olli Etuaho8a176262016-08-16 14:23:01 +03003876void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00003877{
Jamie Madillacb4b812016-11-07 13:50:29 -05003878 if (!sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +05303879 {
Olli Etuaho8a176262016-08-16 14:23:01 +03003880 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003881 }
3882
Arun Patole7e7e68d2015-05-22 12:02:25 +05303883 if (field.type()->getBasicType() != EbtStruct)
3884 {
Olli Etuaho8a176262016-08-16 14:23:01 +03003885 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003886 }
3887
3888 // We're already inside a structure definition at this point, so add
3889 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05303890 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
3891 {
Jonah Ryan-Davisf563fdc2019-01-31 13:53:59 -05003892 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
Olli Etuahof0957992017-12-22 11:10:04 +02003893 if (field.type()->getStruct()->symbolType() == SymbolType::Empty)
3894 {
3895 // This may happen in case there are nested struct definitions. While they are also
3896 // invalid GLSL, they don't cause a syntax error.
3897 reasonStream << "Struct nesting";
3898 }
3899 else
3900 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02003901 reasonStream << "Reference of struct type " << field.type()->getStruct()->name();
Olli Etuahof0957992017-12-22 11:10:04 +02003902 }
3903 reasonStream << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04003904 std::string reason = reasonStream.str();
Olli Etuahofbb1c792018-01-19 16:26:59 +02003905 error(line, reason.c_str(), field.name());
Olli Etuaho8a176262016-08-16 14:23:01 +03003906 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003907 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00003908}
3909
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003910//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003911// Parse an array index expression
3912//
Jamie Madillb98c3a82015-07-23 14:26:04 -04003913TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
3914 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303915 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003916{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003917 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
3918 {
3919 if (baseExpression->getAsSymbolNode())
3920 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303921 error(location, " left of '[' is not of type array, matrix, or vector ",
Olli Etuahofbb1c792018-01-19 16:26:59 +02003922 baseExpression->getAsSymbolNode()->getName());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003923 }
3924 else
3925 {
3926 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
3927 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003928
Olli Etuaho3ec75682017-07-05 17:02:55 +03003929 return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003930 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003931
Jiawei Shaod8105a02017-08-08 09:54:36 +08003932 if (baseExpression->getQualifier() == EvqPerVertexIn)
3933 {
Jiawei Shaobd924af2017-11-16 15:28:04 +08003934 ASSERT(mShaderType == GL_GEOMETRY_SHADER_EXT);
Jiawei Shaod8105a02017-08-08 09:54:36 +08003935 if (mGeometryShaderInputPrimitiveType == EptUndefined)
3936 {
3937 error(location, "missing input primitive declaration before indexing gl_in.", "[");
3938 return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
3939 }
3940 }
3941
Jamie Madill21c1e452014-12-29 11:33:41 -05003942 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
3943
Olli Etuaho1dfd8ae2018-10-01 15:59:59 +03003944 // ANGLE should be able to fold any constant expressions resulting in an integer - but to be
3945 // safe we don't treat "EvqConst" that's evaluated according to the spec as being sufficient
3946 // for constness. Some interpretations of the spec have allowed constant expressions with side
3947 // effects - like array length() method on a non-constant array.
Olli Etuaho36b05142015-11-12 13:10:42 +02003948 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
3949 {
3950 if (baseExpression->isInterfaceBlock())
3951 {
Jiawei Shaobd924af2017-11-16 15:28:04 +08003952 // TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Jiawei Shaod8105a02017-08-08 09:54:36 +08003953 switch (baseExpression->getQualifier())
3954 {
3955 case EvqPerVertexIn:
3956 break;
3957 case EvqUniform:
3958 case EvqBuffer:
3959 error(location,
3960 "array indexes for uniform block arrays and shader storage block arrays "
3961 "must be constant integral expressions",
3962 "[");
3963 break;
3964 default:
Jiawei Shao7e1197e2017-08-24 15:48:38 +08003965 // We can reach here only in error cases.
3966 ASSERT(mDiagnostics->numErrors() > 0);
3967 break;
Jiawei Shaod8105a02017-08-08 09:54:36 +08003968 }
Olli Etuaho36b05142015-11-12 13:10:42 +02003969 }
3970 else if (baseExpression->getQualifier() == EvqFragmentOut)
3971 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003972 error(location,
3973 "array indexes for fragment outputs must be constant integral expressions", "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02003974 }
Olli Etuaho3e960462015-11-12 15:58:39 +02003975 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
3976 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003977 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3e960462015-11-12 15:58:39 +02003978 }
Olli Etuaho36b05142015-11-12 13:10:42 +02003979 }
3980
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003981 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04003982 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003983 // If an out-of-range index is not qualified as constant, the behavior in the spec is
3984 // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
3985 // constant fold expressions that are not constant expressions). The most compatible way to
3986 // handle this case is to report a warning instead of an error and force the index to be in
3987 // the correct range.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003988 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Olli Etuaho56229f12017-07-10 14:16:33 +03003989 int index = 0;
3990 if (indexConstantUnion->getBasicType() == EbtInt)
3991 {
3992 index = indexConstantUnion->getIConst(0);
3993 }
3994 else if (indexConstantUnion->getBasicType() == EbtUInt)
3995 {
3996 index = static_cast<int>(indexConstantUnion->getUConst(0));
3997 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003998
3999 int safeIndex = -1;
4000
Olli Etuahoebee5b32017-11-23 12:56:32 +02004001 if (index < 0)
Jamie Madill7164cf42013-07-08 13:30:59 -04004002 {
Olli Etuahoebee5b32017-11-23 12:56:32 +02004003 outOfRangeError(outOfRangeIndexIsError, location, "index expression is negative", "[]");
4004 safeIndex = 0;
4005 }
4006
4007 if (!baseExpression->getType().isUnsizedArray())
4008 {
4009 if (baseExpression->isArray())
Olli Etuaho90892fb2016-07-14 14:44:51 +03004010 {
Olli Etuahoebee5b32017-11-23 12:56:32 +02004011 if (baseExpression->getQualifier() == EvqFragData && index > 0)
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004012 {
Olli Etuahoebee5b32017-11-23 12:56:32 +02004013 if (!isExtensionEnabled(TExtension::EXT_draw_buffers))
4014 {
4015 outOfRangeError(outOfRangeIndexIsError, location,
4016 "array index for gl_FragData must be zero when "
4017 "GL_EXT_draw_buffers is disabled",
4018 "[]");
4019 safeIndex = 0;
4020 }
4021 }
Olli Etuahof13cadd2017-11-28 10:53:09 +02004022 }
4023 // Only do generic out-of-range check if similar error hasn't already been reported.
4024 if (safeIndex < 0)
4025 {
4026 if (baseExpression->isArray())
Olli Etuahoebee5b32017-11-23 12:56:32 +02004027 {
4028 safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
4029 baseExpression->getOutermostArraySize(),
4030 "array index out of range");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004031 }
Olli Etuahof13cadd2017-11-28 10:53:09 +02004032 else if (baseExpression->isMatrix())
4033 {
4034 safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
4035 baseExpression->getType().getCols(),
4036 "matrix field selection out of range");
4037 }
4038 else
4039 {
4040 ASSERT(baseExpression->isVector());
4041 safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
4042 baseExpression->getType().getNominalSize(),
4043 "vector field selection out of range");
4044 }
Olli Etuahoebee5b32017-11-23 12:56:32 +02004045 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004046
Olli Etuahoebee5b32017-11-23 12:56:32 +02004047 ASSERT(safeIndex >= 0);
4048 // Data of constant unions can't be changed, because it may be shared with other
4049 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
4050 // sanitized object.
4051 if (safeIndex != index || indexConstantUnion->getBasicType() != EbtInt)
4052 {
4053 TConstantUnion *safeConstantUnion = new TConstantUnion();
4054 safeConstantUnion->setIConst(safeIndex);
Olli Etuaho0e99b7a2018-01-12 12:05:48 +02004055 indexExpression = new TIntermConstantUnion(
4056 safeConstantUnion, TType(EbtInt, indexExpression->getPrecision(),
4057 indexExpression->getQualifier()));
Olli Etuahoebee5b32017-11-23 12:56:32 +02004058 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004059
Olli Etuahoebee5b32017-11-23 12:56:32 +02004060 TIntermBinary *node =
4061 new TIntermBinary(EOpIndexDirect, baseExpression, indexExpression);
4062 node->setLine(location);
Olli Etuahoea22b7a2018-01-04 17:09:11 +02004063 return expressionOrFoldedResult(node);
Olli Etuahoebee5b32017-11-23 12:56:32 +02004064 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004065 }
Olli Etuahoebee5b32017-11-23 12:56:32 +02004066
Olli Etuaho94bbed12018-03-20 14:44:53 +02004067 markStaticReadIfSymbol(indexExpression);
Olli Etuahoebee5b32017-11-23 12:56:32 +02004068 TIntermBinary *node = new TIntermBinary(EOpIndexIndirect, baseExpression, indexExpression);
4069 node->setLine(location);
4070 // Indirect indexing can never be constant folded.
4071 return node;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004072}
4073
Olli Etuahoebee5b32017-11-23 12:56:32 +02004074int TParseContext::checkIndexLessThan(bool outOfRangeIndexIsError,
4075 const TSourceLoc &location,
4076 int index,
4077 int arraySize,
4078 const char *reason)
Olli Etuaho90892fb2016-07-14 14:44:51 +03004079{
Olli Etuahoebee5b32017-11-23 12:56:32 +02004080 // Should not reach here with an unsized / runtime-sized array.
4081 ASSERT(arraySize > 0);
Olli Etuahof13cadd2017-11-28 10:53:09 +02004082 // A negative index should already have been checked.
4083 ASSERT(index >= 0);
Olli Etuahoebee5b32017-11-23 12:56:32 +02004084 if (index >= arraySize)
Olli Etuaho90892fb2016-07-14 14:44:51 +03004085 {
Jonah Ryan-Davisf563fdc2019-01-31 13:53:59 -05004086 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
Olli Etuaho4de340a2016-12-16 09:32:03 +00004087 reasonStream << reason << " '" << index << "'";
4088 std::string token = reasonStream.str();
4089 outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
Olli Etuahoebee5b32017-11-23 12:56:32 +02004090 return arraySize - 1;
Olli Etuaho90892fb2016-07-14 14:44:51 +03004091 }
4092 return index;
4093}
4094
Jamie Madillb98c3a82015-07-23 14:26:04 -04004095TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
4096 const TSourceLoc &dotLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02004097 const ImmutableString &fieldString,
Jamie Madillb98c3a82015-07-23 14:26:04 -04004098 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004099{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004100 if (baseExpression->isArray())
4101 {
4102 error(fieldLocation, "cannot apply dot operator to an array", ".");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004103 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004104 }
4105
4106 if (baseExpression->isVector())
4107 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004108 TVector<int> fieldOffsets;
4109 if (!parseVectorFields(fieldLocation, fieldString, baseExpression->getNominalSize(),
4110 &fieldOffsets))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004111 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004112 fieldOffsets.resize(1);
4113 fieldOffsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004114 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004115 TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldOffsets);
4116 node->setLine(dotLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004117
Olli Etuaho765924f2018-01-04 12:48:36 +02004118 return node->fold(mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004119 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004120 else if (baseExpression->getBasicType() == EbtStruct)
4121 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05304122 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04004123 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004124 {
4125 error(dotLocation, "structure has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004126 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004127 }
4128 else
4129 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004130 bool fieldFound = false;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004131 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04004132 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004133 {
Jamie Madill98493dd2013-07-08 14:39:03 -04004134 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004135 {
4136 fieldFound = true;
4137 break;
4138 }
4139 }
4140 if (fieldFound)
4141 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03004142 TIntermTyped *index = CreateIndexNode(i);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004143 index->setLine(fieldLocation);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004144 TIntermBinary *node =
4145 new TIntermBinary(EOpIndexDirectStruct, baseExpression, index);
4146 node->setLine(dotLocation);
Olli Etuahoea22b7a2018-01-04 17:09:11 +02004147 return expressionOrFoldedResult(node);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004148 }
4149 else
4150 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02004151 error(dotLocation, " no such field in structure", fieldString);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004152 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004153 }
4154 }
4155 }
Jamie Madill98493dd2013-07-08 14:39:03 -04004156 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004157 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05304158 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04004159 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004160 {
4161 error(dotLocation, "interface block has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004162 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004163 }
4164 else
4165 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004166 bool fieldFound = false;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004167 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04004168 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004169 {
Jamie Madill98493dd2013-07-08 14:39:03 -04004170 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004171 {
4172 fieldFound = true;
4173 break;
4174 }
4175 }
4176 if (fieldFound)
4177 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03004178 TIntermTyped *index = CreateIndexNode(i);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004179 index->setLine(fieldLocation);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004180 TIntermBinary *node =
4181 new TIntermBinary(EOpIndexDirectInterfaceBlock, baseExpression, index);
4182 node->setLine(dotLocation);
4183 // Indexing interface blocks can never be constant folded.
4184 return node;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004185 }
4186 else
4187 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02004188 error(dotLocation, " no such field in interface block", fieldString);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004189 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004190 }
4191 }
4192 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004193 else
4194 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004195 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004196 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03004197 error(dotLocation, " field selection requires structure or vector on left hand side",
Olli Etuahofbb1c792018-01-19 16:26:59 +02004198 fieldString);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004199 }
4200 else
4201 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05304202 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03004203 " field selection requires structure, vector, or interface block on left hand "
4204 "side",
Olli Etuahofbb1c792018-01-19 16:26:59 +02004205 fieldString);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004206 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004207 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004208 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004209}
4210
Olli Etuahofbb1c792018-01-19 16:26:59 +02004211TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qualifierType,
Jamie Madillb98c3a82015-07-23 14:26:04 -04004212 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004213{
Jamie Madill2f294c92017-11-20 14:47:26 -05004214 TLayoutQualifier qualifier = TLayoutQualifier::Create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004215
4216 if (qualifierType == "shared")
4217 {
Jamie Madillacb4b812016-11-07 13:50:29 -05004218 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07004219 {
4220 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
4221 }
Jamie Madilla5efff92013-06-06 11:56:47 -04004222 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004223 }
4224 else if (qualifierType == "packed")
4225 {
Jamie Madillacb4b812016-11-07 13:50:29 -05004226 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07004227 {
4228 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
4229 }
Jamie Madilla5efff92013-06-06 11:56:47 -04004230 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004231 }
Qin Jiajiaca68d982017-09-18 16:41:56 +08004232 else if (qualifierType == "std430")
4233 {
4234 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4235 qualifier.blockStorage = EbsStd430;
4236 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004237 else if (qualifierType == "std140")
4238 {
Jamie Madilla5efff92013-06-06 11:56:47 -04004239 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004240 }
4241 else if (qualifierType == "row_major")
4242 {
Jamie Madilla5efff92013-06-06 11:56:47 -04004243 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004244 }
4245 else if (qualifierType == "column_major")
4246 {
Jamie Madilla5efff92013-06-06 11:56:47 -04004247 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004248 }
4249 else if (qualifierType == "location")
4250 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00004251 error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
Olli Etuahofbb1c792018-01-19 16:26:59 +02004252 qualifierType);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004253 }
Olli Etuaho703671e2017-11-08 17:47:18 +02004254 else if (qualifierType == "yuv" && mShaderType == GL_FRAGMENT_SHADER)
Andrei Volykhina5527072017-03-22 16:46:30 +03004255 {
Olli Etuaho703671e2017-11-08 17:47:18 +02004256 if (checkCanUseExtension(qualifierTypeLine, TExtension::EXT_YUV_target))
4257 {
4258 qualifier.yuv = true;
4259 }
Andrei Volykhina5527072017-03-22 16:46:30 +03004260 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004261 else if (qualifierType == "rgba32f")
4262 {
4263 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4264 qualifier.imageInternalFormat = EiifRGBA32F;
4265 }
4266 else if (qualifierType == "rgba16f")
4267 {
4268 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4269 qualifier.imageInternalFormat = EiifRGBA16F;
4270 }
4271 else if (qualifierType == "r32f")
4272 {
4273 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4274 qualifier.imageInternalFormat = EiifR32F;
4275 }
4276 else if (qualifierType == "rgba8")
4277 {
4278 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4279 qualifier.imageInternalFormat = EiifRGBA8;
4280 }
4281 else if (qualifierType == "rgba8_snorm")
4282 {
4283 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4284 qualifier.imageInternalFormat = EiifRGBA8_SNORM;
4285 }
4286 else if (qualifierType == "rgba32i")
4287 {
4288 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4289 qualifier.imageInternalFormat = EiifRGBA32I;
4290 }
4291 else if (qualifierType == "rgba16i")
4292 {
4293 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4294 qualifier.imageInternalFormat = EiifRGBA16I;
4295 }
4296 else if (qualifierType == "rgba8i")
4297 {
4298 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4299 qualifier.imageInternalFormat = EiifRGBA8I;
4300 }
4301 else if (qualifierType == "r32i")
4302 {
4303 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4304 qualifier.imageInternalFormat = EiifR32I;
4305 }
4306 else if (qualifierType == "rgba32ui")
4307 {
4308 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4309 qualifier.imageInternalFormat = EiifRGBA32UI;
4310 }
4311 else if (qualifierType == "rgba16ui")
4312 {
4313 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4314 qualifier.imageInternalFormat = EiifRGBA16UI;
4315 }
4316 else if (qualifierType == "rgba8ui")
4317 {
4318 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4319 qualifier.imageInternalFormat = EiifRGBA8UI;
4320 }
4321 else if (qualifierType == "r32ui")
4322 {
4323 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4324 qualifier.imageInternalFormat = EiifR32UI;
4325 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004326 else if (qualifierType == "points" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4327 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004328 {
4329 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4330 qualifier.primitiveType = EptPoints;
4331 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004332 else if (qualifierType == "lines" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4333 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004334 {
4335 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4336 qualifier.primitiveType = EptLines;
4337 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004338 else if (qualifierType == "lines_adjacency" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4339 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004340 {
4341 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4342 qualifier.primitiveType = EptLinesAdjacency;
4343 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004344 else if (qualifierType == "triangles" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4345 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004346 {
4347 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4348 qualifier.primitiveType = EptTriangles;
4349 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004350 else if (qualifierType == "triangles_adjacency" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4351 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004352 {
4353 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4354 qualifier.primitiveType = EptTrianglesAdjacency;
4355 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004356 else if (qualifierType == "line_strip" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4357 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004358 {
4359 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4360 qualifier.primitiveType = EptLineStrip;
4361 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004362 else if (qualifierType == "triangle_strip" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4363 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004364 {
4365 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4366 qualifier.primitiveType = EptTriangleStrip;
4367 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004368
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004369 else
4370 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02004371 error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004372 }
4373
Jamie Madilla5efff92013-06-06 11:56:47 -04004374 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004375}
4376
Olli Etuahofbb1c792018-01-19 16:26:59 +02004377void TParseContext::parseLocalSize(const ImmutableString &qualifierType,
Martin Radev802abe02016-08-04 17:48:32 +03004378 const TSourceLoc &qualifierTypeLine,
4379 int intValue,
4380 const TSourceLoc &intValueLine,
4381 const std::string &intValueString,
4382 size_t index,
Martin Radev4c4c8e72016-08-04 12:25:34 +03004383 sh::WorkGroupSize *localSize)
Martin Radev802abe02016-08-04 17:48:32 +03004384{
Olli Etuaho856c4972016-08-08 11:38:39 +03004385 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03004386 if (intValue < 1)
4387 {
Jonah Ryan-Davisf563fdc2019-01-31 13:53:59 -05004388 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
Olli Etuaho4de340a2016-12-16 09:32:03 +00004389 reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
4390 std::string reason = reasonStream.str();
4391 error(intValueLine, reason.c_str(), intValueString.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03004392 }
4393 (*localSize)[index] = intValue;
4394}
4395
Olli Etuaho09b04a22016-12-15 13:30:26 +00004396void TParseContext::parseNumViews(int intValue,
4397 const TSourceLoc &intValueLine,
4398 const std::string &intValueString,
4399 int *numViews)
4400{
4401 // This error is only specified in WebGL, but tightens unspecified behavior in the native
4402 // specification.
4403 if (intValue < 1)
4404 {
4405 error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
4406 }
4407 *numViews = intValue;
4408}
4409
Shaob5cc1192017-07-06 10:47:20 +08004410void TParseContext::parseInvocations(int intValue,
4411 const TSourceLoc &intValueLine,
4412 const std::string &intValueString,
4413 int *numInvocations)
4414{
4415 // Although SPEC isn't clear whether invocations can be less than 1, we add this limit because
4416 // it doesn't make sense to accept invocations <= 0.
4417 if (intValue < 1 || intValue > mMaxGeometryShaderInvocations)
4418 {
4419 error(intValueLine,
4420 "out of range: invocations must be in the range of [1, "
4421 "MAX_GEOMETRY_SHADER_INVOCATIONS_OES]",
4422 intValueString.c_str());
4423 }
4424 else
4425 {
4426 *numInvocations = intValue;
4427 }
4428}
4429
4430void TParseContext::parseMaxVertices(int intValue,
4431 const TSourceLoc &intValueLine,
4432 const std::string &intValueString,
4433 int *maxVertices)
4434{
4435 // Although SPEC isn't clear whether max_vertices can be less than 0, we add this limit because
4436 // it doesn't make sense to accept max_vertices < 0.
4437 if (intValue < 0 || intValue > mMaxGeometryShaderMaxVertices)
4438 {
4439 error(
4440 intValueLine,
4441 "out of range: max_vertices must be in the range of [0, gl_MaxGeometryOutputVertices]",
4442 intValueString.c_str());
4443 }
4444 else
4445 {
4446 *maxVertices = intValue;
4447 }
4448}
4449
Olli Etuahoa78092c2018-09-26 14:16:13 +03004450void TParseContext::parseIndexLayoutQualifier(int intValue,
4451 const TSourceLoc &intValueLine,
4452 const std::string &intValueString,
4453 int *index)
4454{
4455 // EXT_blend_func_extended specifies that most validation should happen at link time, but since
4456 // we're validating output variable locations at compile time, it makes sense to validate that
4457 // index is 0 or 1 also at compile time. Also since we use "-1" as a placeholder for unspecified
4458 // index, we can't accept it here.
4459 if (intValue < 0 || intValue > 1)
4460 {
4461 error(intValueLine, "out of range: index layout qualifier can only be 0 or 1",
4462 intValueString.c_str());
4463 }
4464 else
4465 {
4466 *index = intValue;
4467 }
4468}
4469
Olli Etuahofbb1c792018-01-19 16:26:59 +02004470TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qualifierType,
Jamie Madillb98c3a82015-07-23 14:26:04 -04004471 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04004472 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05304473 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004474{
Jamie Madill2f294c92017-11-20 14:47:26 -05004475 TLayoutQualifier qualifier = TLayoutQualifier::Create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004476
Martin Radev802abe02016-08-04 17:48:32 +03004477 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004478
Martin Radev802abe02016-08-04 17:48:32 +03004479 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004480 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04004481 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004482 if (intValue < 0)
4483 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00004484 error(intValueLine, "out of range: location must be non-negative",
4485 intValueString.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004486 }
4487 else
4488 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05004489 qualifier.location = intValue;
Olli Etuaho87d410c2016-09-05 13:33:26 +03004490 qualifier.locationsSpecified = 1;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004491 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004492 }
Olli Etuaho43364892017-02-13 16:00:12 +00004493 else if (qualifierType == "binding")
4494 {
4495 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4496 if (intValue < 0)
4497 {
4498 error(intValueLine, "out of range: binding must be non-negative",
4499 intValueString.c_str());
4500 }
4501 else
4502 {
4503 qualifier.binding = intValue;
4504 }
4505 }
jchen104cdac9e2017-05-08 11:01:20 +08004506 else if (qualifierType == "offset")
4507 {
4508 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4509 if (intValue < 0)
4510 {
4511 error(intValueLine, "out of range: offset must be non-negative",
4512 intValueString.c_str());
4513 }
4514 else
4515 {
4516 qualifier.offset = intValue;
4517 }
4518 }
Martin Radev802abe02016-08-04 17:48:32 +03004519 else if (qualifierType == "local_size_x")
4520 {
4521 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
4522 &qualifier.localSize);
4523 }
4524 else if (qualifierType == "local_size_y")
4525 {
4526 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
4527 &qualifier.localSize);
4528 }
4529 else if (qualifierType == "local_size_z")
4530 {
4531 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
4532 &qualifier.localSize);
4533 }
Olli Etuaho703671e2017-11-08 17:47:18 +02004534 else if (qualifierType == "num_views" && mShaderType == GL_VERTEX_SHADER)
Olli Etuaho09b04a22016-12-15 13:30:26 +00004535 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07004536 if (checkCanUseExtension(qualifierTypeLine, TExtension::OVR_multiview2))
Olli Etuaho703671e2017-11-08 17:47:18 +02004537 {
4538 parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
4539 }
Olli Etuaho09b04a22016-12-15 13:30:26 +00004540 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004541 else if (qualifierType == "invocations" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4542 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004543 {
4544 parseInvocations(intValue, intValueLine, intValueString, &qualifier.invocations);
4545 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004546 else if (qualifierType == "max_vertices" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4547 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004548 {
4549 parseMaxVertices(intValue, intValueLine, intValueString, &qualifier.maxVertices);
4550 }
Olli Etuahoa78092c2018-09-26 14:16:13 +03004551 else if (qualifierType == "index" && mShaderType == GL_FRAGMENT_SHADER &&
4552 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_blend_func_extended))
4553 {
4554 parseIndexLayoutQualifier(intValue, intValueLine, intValueString, &qualifier.index);
4555 }
Martin Radev802abe02016-08-04 17:48:32 +03004556 else
4557 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02004558 error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
Martin Radev802abe02016-08-04 17:48:32 +03004559 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004560
Jamie Madilla5efff92013-06-06 11:56:47 -04004561 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004562}
4563
Olli Etuaho613b9592016-09-05 12:05:53 +03004564TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
4565{
4566 return new TTypeQualifierBuilder(
4567 new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
4568 mShaderVersion);
4569}
4570
Olli Etuahocce89652017-06-19 16:04:09 +03004571TStorageQualifierWrapper *TParseContext::parseGlobalStorageQualifier(TQualifier qualifier,
4572 const TSourceLoc &loc)
4573{
4574 checkIsAtGlobalLevel(loc, getQualifierString(qualifier));
4575 return new TStorageQualifierWrapper(qualifier, loc);
4576}
4577
4578TStorageQualifierWrapper *TParseContext::parseVaryingQualifier(const TSourceLoc &loc)
4579{
4580 if (getShaderType() == GL_VERTEX_SHADER)
4581 {
4582 return parseGlobalStorageQualifier(EvqVaryingOut, loc);
4583 }
4584 return parseGlobalStorageQualifier(EvqVaryingIn, loc);
4585}
4586
4587TStorageQualifierWrapper *TParseContext::parseInQualifier(const TSourceLoc &loc)
4588{
4589 if (declaringFunction())
4590 {
4591 return new TStorageQualifierWrapper(EvqIn, loc);
4592 }
Shaob5cc1192017-07-06 10:47:20 +08004593
4594 switch (getShaderType())
Olli Etuahocce89652017-06-19 16:04:09 +03004595 {
Shaob5cc1192017-07-06 10:47:20 +08004596 case GL_VERTEX_SHADER:
Olli Etuahocce89652017-06-19 16:04:09 +03004597 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07004598 if (mShaderVersion < 300 && !isExtensionEnabled(TExtension::OVR_multiview2))
Shaob5cc1192017-07-06 10:47:20 +08004599 {
4600 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
4601 }
4602 return new TStorageQualifierWrapper(EvqVertexIn, loc);
Olli Etuahocce89652017-06-19 16:04:09 +03004603 }
Shaob5cc1192017-07-06 10:47:20 +08004604 case GL_FRAGMENT_SHADER:
Olli Etuahocce89652017-06-19 16:04:09 +03004605 {
Shaob5cc1192017-07-06 10:47:20 +08004606 if (mShaderVersion < 300)
4607 {
4608 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
4609 }
4610 return new TStorageQualifierWrapper(EvqFragmentIn, loc);
Olli Etuahocce89652017-06-19 16:04:09 +03004611 }
Shaob5cc1192017-07-06 10:47:20 +08004612 case GL_COMPUTE_SHADER:
4613 {
4614 return new TStorageQualifierWrapper(EvqComputeIn, loc);
4615 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004616 case GL_GEOMETRY_SHADER_EXT:
Shaob5cc1192017-07-06 10:47:20 +08004617 {
4618 return new TStorageQualifierWrapper(EvqGeometryIn, loc);
4619 }
4620 default:
4621 {
4622 UNREACHABLE();
4623 return new TStorageQualifierWrapper(EvqLast, loc);
4624 }
Olli Etuahocce89652017-06-19 16:04:09 +03004625 }
Olli Etuahocce89652017-06-19 16:04:09 +03004626}
4627
4628TStorageQualifierWrapper *TParseContext::parseOutQualifier(const TSourceLoc &loc)
4629{
4630 if (declaringFunction())
4631 {
4632 return new TStorageQualifierWrapper(EvqOut, loc);
4633 }
Shaob5cc1192017-07-06 10:47:20 +08004634 switch (getShaderType())
Olli Etuahocce89652017-06-19 16:04:09 +03004635 {
Shaob5cc1192017-07-06 10:47:20 +08004636 case GL_VERTEX_SHADER:
4637 {
4638 if (mShaderVersion < 300)
4639 {
4640 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
4641 }
4642 return new TStorageQualifierWrapper(EvqVertexOut, loc);
4643 }
4644 case GL_FRAGMENT_SHADER:
4645 {
4646 if (mShaderVersion < 300)
4647 {
4648 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
4649 }
4650 return new TStorageQualifierWrapper(EvqFragmentOut, loc);
4651 }
4652 case GL_COMPUTE_SHADER:
4653 {
4654 error(loc, "storage qualifier isn't supported in compute shaders", "out");
4655 return new TStorageQualifierWrapper(EvqLast, loc);
4656 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004657 case GL_GEOMETRY_SHADER_EXT:
Shaob5cc1192017-07-06 10:47:20 +08004658 {
4659 return new TStorageQualifierWrapper(EvqGeometryOut, loc);
4660 }
4661 default:
4662 {
4663 UNREACHABLE();
4664 return new TStorageQualifierWrapper(EvqLast, loc);
4665 }
Olli Etuahocce89652017-06-19 16:04:09 +03004666 }
Olli Etuahocce89652017-06-19 16:04:09 +03004667}
4668
4669TStorageQualifierWrapper *TParseContext::parseInOutQualifier(const TSourceLoc &loc)
4670{
4671 if (!declaringFunction())
4672 {
4673 error(loc, "invalid qualifier: can be only used with function parameters", "inout");
4674 }
4675 return new TStorageQualifierWrapper(EvqInOut, loc);
4676}
4677
Jamie Madillb98c3a82015-07-23 14:26:04 -04004678TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03004679 TLayoutQualifier rightQualifier,
4680 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004681{
Martin Radevc28888b2016-07-22 15:27:42 +03004682 return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
Olli Etuaho77ba4082016-12-16 12:01:18 +00004683 mDiagnostics);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004684}
4685
Olli Etuahofbb1c792018-01-19 16:26:59 +02004686TDeclarator *TParseContext::parseStructDeclarator(const ImmutableString &identifier,
4687 const TSourceLoc &loc)
Olli Etuahocce89652017-06-19 16:04:09 +03004688{
Olli Etuahofbb1c792018-01-19 16:26:59 +02004689 checkIsNotReserved(loc, identifier);
Olli Etuahod5f44c92017-11-29 17:15:40 +02004690 return new TDeclarator(identifier, loc);
Olli Etuahocce89652017-06-19 16:04:09 +03004691}
4692
Olli Etuahofbb1c792018-01-19 16:26:59 +02004693TDeclarator *TParseContext::parseStructArrayDeclarator(const ImmutableString &identifier,
Olli Etuahod5f44c92017-11-29 17:15:40 +02004694 const TSourceLoc &loc,
4695 const TVector<unsigned int> *arraySizes)
Olli Etuahocce89652017-06-19 16:04:09 +03004696{
Olli Etuahofbb1c792018-01-19 16:26:59 +02004697 checkIsNotReserved(loc, identifier);
Olli Etuahod5f44c92017-11-29 17:15:40 +02004698 return new TDeclarator(identifier, arraySizes, loc);
Olli Etuahocce89652017-06-19 16:04:09 +03004699}
4700
Olli Etuaho722bfb52017-10-26 17:00:11 +03004701void TParseContext::checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin,
4702 const TFieldList::const_iterator end,
Olli Etuahofbb1c792018-01-19 16:26:59 +02004703 const ImmutableString &name,
Olli Etuaho722bfb52017-10-26 17:00:11 +03004704 const TSourceLoc &location)
4705{
4706 for (auto fieldIter = begin; fieldIter != end; ++fieldIter)
4707 {
4708 if ((*fieldIter)->name() == name)
4709 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02004710 error(location, "duplicate field name in structure", name);
Olli Etuaho722bfb52017-10-26 17:00:11 +03004711 }
4712 }
4713}
4714
4715TFieldList *TParseContext::addStructFieldList(TFieldList *fields, const TSourceLoc &location)
4716{
4717 for (TFieldList::const_iterator fieldIter = fields->begin(); fieldIter != fields->end();
4718 ++fieldIter)
4719 {
4720 checkDoesNotHaveDuplicateFieldName(fields->begin(), fieldIter, (*fieldIter)->name(),
4721 location);
4722 }
4723 return fields;
4724}
4725
Olli Etuaho4de340a2016-12-16 09:32:03 +00004726TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
4727 const TFieldList *newlyAddedFields,
4728 const TSourceLoc &location)
4729{
4730 for (TField *field : *newlyAddedFields)
4731 {
Olli Etuaho722bfb52017-10-26 17:00:11 +03004732 checkDoesNotHaveDuplicateFieldName(processedFields->begin(), processedFields->end(),
4733 field->name(), location);
Olli Etuaho4de340a2016-12-16 09:32:03 +00004734 processedFields->push_back(field);
4735 }
4736 return processedFields;
4737}
4738
Martin Radev70866b82016-07-22 15:27:42 +03004739TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
4740 const TTypeQualifierBuilder &typeQualifierBuilder,
4741 TPublicType *typeSpecifier,
Olli Etuahod5f44c92017-11-29 17:15:40 +02004742 const TDeclaratorList *declaratorList)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04004743{
Olli Etuaho77ba4082016-12-16 12:01:18 +00004744 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04004745
Martin Radev70866b82016-07-22 15:27:42 +03004746 typeSpecifier->qualifier = typeQualifier.qualifier;
4747 typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03004748 typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03004749 typeSpecifier->invariant = typeQualifier.invariant;
4750 if (typeQualifier.precision != EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +05304751 {
Martin Radev70866b82016-07-22 15:27:42 +03004752 typeSpecifier->precision = typeQualifier.precision;
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04004753 }
Olli Etuahod5f44c92017-11-29 17:15:40 +02004754 return addStructDeclaratorList(*typeSpecifier, declaratorList);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04004755}
4756
Jamie Madillb98c3a82015-07-23 14:26:04 -04004757TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
Olli Etuahod5f44c92017-11-29 17:15:40 +02004758 const TDeclaratorList *declaratorList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004759{
Martin Radev4a9cd802016-09-01 16:51:51 +03004760 checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
4761 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03004762
Olli Etuahofbb1c792018-01-19 16:26:59 +02004763 checkIsNonVoid(typeSpecifier.getLine(), (*declaratorList)[0]->name(),
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004764 typeSpecifier.getBasicType());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004765
Martin Radev4a9cd802016-09-01 16:51:51 +03004766 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03004767
Olli Etuahod5f44c92017-11-29 17:15:40 +02004768 TFieldList *fieldList = new TFieldList();
4769
4770 for (const TDeclarator *declarator : *declaratorList)
Arun Patole7e7e68d2015-05-22 12:02:25 +05304771 {
Olli Etuahod5f44c92017-11-29 17:15:40 +02004772 TType *type = new TType(typeSpecifier);
4773 if (declarator->isArray())
Arun Patole7e7e68d2015-05-22 12:02:25 +05304774 {
Olli Etuahod5f44c92017-11-29 17:15:40 +02004775 // Don't allow arrays of arrays in ESSL < 3.10.
Olli Etuahoe0803872017-08-23 15:30:23 +03004776 checkArrayElementIsNotArray(typeSpecifier.getLine(), typeSpecifier);
Olli Etuahod5f44c92017-11-29 17:15:40 +02004777 type->makeArrays(*declarator->arraySizes());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004778 }
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004779
Jamie Madillf5557ac2018-06-15 09:46:58 -04004780 TField *field =
4781 new TField(type, declarator->name(), declarator->line(), SymbolType::UserDefined);
Olli Etuahod5f44c92017-11-29 17:15:40 +02004782 checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *field);
4783 fieldList->push_back(field);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004784 }
4785
Olli Etuahod5f44c92017-11-29 17:15:40 +02004786 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004787}
4788
Martin Radev4a9cd802016-09-01 16:51:51 +03004789TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
4790 const TSourceLoc &nameLine,
Olli Etuahofbb1c792018-01-19 16:26:59 +02004791 const ImmutableString &structName,
Martin Radev4a9cd802016-09-01 16:51:51 +03004792 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004793{
Olli Etuaho9d4d7f02017-12-07 17:11:41 +01004794 SymbolType structSymbolType = SymbolType::UserDefined;
Olli Etuahofbb1c792018-01-19 16:26:59 +02004795 if (structName.empty())
Olli Etuaho9d4d7f02017-12-07 17:11:41 +01004796 {
Olli Etuaho9d4d7f02017-12-07 17:11:41 +01004797 structSymbolType = SymbolType::Empty;
4798 }
4799 TStructure *structure = new TStructure(&symbolTable, structName, fieldList, structSymbolType);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004800
Jamie Madill9b820842015-02-12 10:40:10 -05004801 // Store a bool in the struct if we're at global scope, to allow us to
4802 // skip the local struct scoping workaround in HLSL.
Jamie Madill9b820842015-02-12 10:40:10 -05004803 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04004804
Olli Etuaho9d4d7f02017-12-07 17:11:41 +01004805 if (structSymbolType != SymbolType::Empty)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004806 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02004807 checkIsNotReserved(nameLine, structName);
Olli Etuaho437664b2018-02-28 15:38:14 +02004808 if (!symbolTable.declare(structure))
Arun Patole7e7e68d2015-05-22 12:02:25 +05304809 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02004810 error(nameLine, "redefinition of a struct", structName);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004811 }
4812 }
4813
4814 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04004815 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004816 {
Olli Etuahoebee5b32017-11-23 12:56:32 +02004817 TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04004818 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004819 switch (qualifier)
4820 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004821 case EvqGlobal:
4822 case EvqTemporary:
4823 break;
4824 default:
4825 error(field.line(), "invalid qualifier on struct member",
4826 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04004827 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004828 }
Martin Radev70866b82016-07-22 15:27:42 +03004829 if (field.type()->isInvariant())
4830 {
4831 error(field.line(), "invalid qualifier on struct member", "invariant");
4832 }
jchen104cdac9e2017-05-08 11:01:20 +08004833 // ESSL 3.10 section 4.1.8 -- atomic_uint or images are not allowed as structure member.
4834 if (IsImage(field.type()->getBasicType()) || IsAtomicCounter(field.type()->getBasicType()))
Martin Radev2cc85b32016-08-05 16:22:53 +03004835 {
4836 error(field.line(), "disallowed type in struct", field.type()->getBasicString());
4837 }
4838
Olli Etuahoebee5b32017-11-23 12:56:32 +02004839 checkIsNotUnsizedArray(field.line(), "array members of structs must specify a size",
Olli Etuahofbb1c792018-01-19 16:26:59 +02004840 field.name(), field.type());
Olli Etuahoebee5b32017-11-23 12:56:32 +02004841
Olli Etuaho43364892017-02-13 16:00:12 +00004842 checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
4843
Olli Etuahoa78092c2018-09-26 14:16:13 +03004844 checkIndexIsNotSpecified(field.line(), field.type()->getLayoutQualifier().index);
4845
Olli Etuaho43364892017-02-13 16:00:12 +00004846 checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);
Martin Radev70866b82016-07-22 15:27:42 +03004847
4848 checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004849 }
4850
Martin Radev4a9cd802016-09-01 16:51:51 +03004851 TTypeSpecifierNonArray typeSpecifierNonArray;
Olli Etuaho0f684632017-07-13 12:42:15 +03004852 typeSpecifierNonArray.initializeStruct(structure, true, structLine);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004853 exitStructDeclaration();
4854
Martin Radev4a9cd802016-09-01 16:51:51 +03004855 return typeSpecifierNonArray;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004856}
4857
Jamie Madillb98c3a82015-07-23 14:26:04 -04004858TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01004859 TIntermBlock *statementList,
Jamie Madillb98c3a82015-07-23 14:26:04 -04004860 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02004861{
Olli Etuaho53f076f2015-02-20 10:55:14 +02004862 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04004863 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02004864 init->isVector())
4865 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004866 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
4867 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004868 return nullptr;
4869 }
4870
Olli Etuaho923ecef2017-10-11 12:01:38 +03004871 ASSERT(statementList);
Olli Etuahod05f9642018-03-05 12:13:26 +02004872 if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
Olli Etuahoac5274d2015-02-20 10:19:08 +02004873 {
Olli Etuahocbcb96f2017-10-19 14:14:06 +03004874 ASSERT(mDiagnostics->numErrors() > 0);
Olli Etuaho923ecef2017-10-11 12:01:38 +03004875 return nullptr;
Olli Etuahoac5274d2015-02-20 10:19:08 +02004876 }
4877
Olli Etuaho94bbed12018-03-20 14:44:53 +02004878 markStaticReadIfSymbol(init);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004879 TIntermSwitch *node = new TIntermSwitch(init, statementList);
4880 node->setLine(loc);
Olli Etuahoa3a36662015-02-17 13:46:51 +02004881 return node;
4882}
4883
4884TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
4885{
Olli Etuaho53f076f2015-02-20 10:55:14 +02004886 if (mSwitchNestingLevel == 0)
4887 {
4888 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004889 return nullptr;
4890 }
4891 if (condition == nullptr)
4892 {
4893 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004894 return nullptr;
4895 }
4896 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04004897 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02004898 {
4899 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004900 }
4901 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho1dfd8ae2018-10-01 15:59:59 +03004902 // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be
4903 // safe against corner cases we still check for conditionConst. Some interpretations of the
4904 // spec have allowed constant expressions with side effects - like array length() method on a
4905 // non-constant array.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02004906 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02004907 {
4908 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004909 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004910 TIntermCase *node = new TIntermCase(condition);
4911 node->setLine(loc);
Olli Etuahoa3a36662015-02-17 13:46:51 +02004912 return node;
4913}
4914
4915TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
4916{
Olli Etuaho53f076f2015-02-20 10:55:14 +02004917 if (mSwitchNestingLevel == 0)
4918 {
4919 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004920 return nullptr;
4921 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004922 TIntermCase *node = new TIntermCase(nullptr);
4923 node->setLine(loc);
Olli Etuahoa3a36662015-02-17 13:46:51 +02004924 return node;
4925}
4926
Jamie Madillb98c3a82015-07-23 14:26:04 -04004927TIntermTyped *TParseContext::createUnaryMath(TOperator op,
4928 TIntermTyped *child,
Olli Etuaho5fec7ab2018-04-04 11:58:33 +03004929 const TSourceLoc &loc,
4930 const TFunction *func)
Olli Etuaho69c11b52015-03-26 12:59:00 +02004931{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004932 ASSERT(child != nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02004933
4934 switch (op)
4935 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004936 case EOpLogicalNot:
4937 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
4938 child->isVector())
4939 {
Olli Etuaho72e35892018-06-20 11:43:08 +03004940 unaryOpError(loc, GetOperatorString(op), child->getType());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004941 return nullptr;
4942 }
4943 break;
4944 case EOpBitwiseNot:
4945 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
4946 child->isMatrix() || child->isArray())
4947 {
Olli Etuaho72e35892018-06-20 11:43:08 +03004948 unaryOpError(loc, GetOperatorString(op), child->getType());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004949 return nullptr;
4950 }
4951 break;
4952 case EOpPostIncrement:
4953 case EOpPreIncrement:
4954 case EOpPostDecrement:
4955 case EOpPreDecrement:
4956 case EOpNegative:
4957 case EOpPositive:
Olli Etuaho94050052017-05-08 14:17:44 +03004958 if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() ||
4959 child->getBasicType() == EbtBool || child->isArray() ||
Geoff Lang6aab06e2018-11-20 14:04:11 -05004960 child->getBasicType() == EbtVoid || IsOpaqueType(child->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -04004961 {
Olli Etuaho72e35892018-06-20 11:43:08 +03004962 unaryOpError(loc, GetOperatorString(op), child->getType());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004963 return nullptr;
4964 }
Nico Weber41b072b2018-02-09 10:01:32 -05004965 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004966 // Operators for built-ins are already type checked against their prototype.
4967 default:
4968 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02004969 }
4970
Jiajia Qinbc585152017-06-23 15:42:17 +08004971 if (child->getMemoryQualifier().writeonly)
4972 {
Olli Etuaho72e35892018-06-20 11:43:08 +03004973 unaryOpError(loc, GetOperatorString(op), child->getType());
Jiajia Qinbc585152017-06-23 15:42:17 +08004974 return nullptr;
4975 }
4976
Olli Etuaho94bbed12018-03-20 14:44:53 +02004977 markStaticReadIfSymbol(child);
Olli Etuaho5fec7ab2018-04-04 11:58:33 +03004978 TIntermUnary *node = new TIntermUnary(op, child, func);
Olli Etuahof119a262016-08-19 15:54:22 +03004979 node->setLine(loc);
Olli Etuahof119a262016-08-19 15:54:22 +03004980
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004981 return node->fold(mDiagnostics);
Olli Etuaho69c11b52015-03-26 12:59:00 +02004982}
4983
Olli Etuaho09b22472015-02-11 11:47:26 +02004984TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
4985{
Olli Etuahocce89652017-06-19 16:04:09 +03004986 ASSERT(op != EOpNull);
Olli Etuaho5fec7ab2018-04-04 11:58:33 +03004987 TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02004988 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02004989 {
Olli Etuaho09b22472015-02-11 11:47:26 +02004990 return child;
4991 }
4992 return node;
4993}
4994
Jamie Madillb98c3a82015-07-23 14:26:04 -04004995TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
4996 TIntermTyped *child,
4997 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004998{
Olli Etuaho856c4972016-08-08 11:38:39 +03004999 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02005000 return addUnaryMath(op, child, loc);
5001}
5002
Olli Etuaho765924f2018-01-04 12:48:36 +02005003TIntermTyped *TParseContext::expressionOrFoldedResult(TIntermTyped *expression)
5004{
5005 // If we can, we should return the folded version of the expression for subsequent parsing. This
5006 // enables folding the containing expression during parsing as well, instead of the separate
5007 // FoldExpressions() step where folding nested expressions requires multiple full AST
5008 // traversals.
5009
5010 // Even if folding fails the fold() functions return some node representing the expression,
5011 // typically the original node. So "folded" can be assumed to be non-null.
5012 TIntermTyped *folded = expression->fold(mDiagnostics);
5013 ASSERT(folded != nullptr);
5014 if (folded->getQualifier() == expression->getQualifier())
5015 {
5016 // We need this expression to have the correct qualifier when validating the consuming
5017 // expression. So we can only return the folded node from here in case it has the same
5018 // qualifier as the original expression. In this kind of a cases the qualifier of the folded
5019 // node is EvqConst, whereas the qualifier of the expression is EvqTemporary:
5020 // 1. (true ? 1.0 : non_constant)
5021 // 2. (non_constant, 1.0)
5022 return folded;
5023 }
5024 return expression;
5025}
5026
Jamie Madillb98c3a82015-07-23 14:26:04 -04005027bool TParseContext::binaryOpCommonCheck(TOperator op,
5028 TIntermTyped *left,
5029 TIntermTyped *right,
5030 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02005031{
jchen10b4cf5652017-05-05 18:51:17 +08005032 // Check opaque types are not allowed to be operands in expressions other than array indexing
5033 // and structure member selection.
5034 if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType()))
5035 {
5036 switch (op)
5037 {
5038 case EOpIndexDirect:
5039 case EOpIndexIndirect:
5040 break;
jchen10b4cf5652017-05-05 18:51:17 +08005041
5042 default:
Nico Weberb5db2b42018-02-12 15:31:56 -05005043 ASSERT(op != EOpIndexDirectStruct);
jchen10b4cf5652017-05-05 18:51:17 +08005044 error(loc, "Invalid operation for variables with an opaque type",
5045 GetOperatorString(op));
5046 return false;
5047 }
5048 }
jchen10cc2a10e2017-05-03 14:05:12 +08005049
Jiajia Qinbc585152017-06-23 15:42:17 +08005050 if (right->getMemoryQualifier().writeonly)
5051 {
5052 error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op));
5053 return false;
5054 }
5055
5056 if (left->getMemoryQualifier().writeonly)
5057 {
5058 switch (op)
5059 {
5060 case EOpAssign:
5061 case EOpInitialize:
5062 case EOpIndexDirect:
5063 case EOpIndexIndirect:
5064 case EOpIndexDirectStruct:
5065 case EOpIndexDirectInterfaceBlock:
5066 break;
5067 default:
5068 error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op));
5069 return false;
5070 }
5071 }
5072
Olli Etuaho244be012016-08-18 15:26:02 +03005073 if (left->getType().getStruct() || right->getType().getStruct())
5074 {
5075 switch (op)
5076 {
5077 case EOpIndexDirectStruct:
5078 ASSERT(left->getType().getStruct());
5079 break;
5080 case EOpEqual:
5081 case EOpNotEqual:
5082 case EOpAssign:
5083 case EOpInitialize:
5084 if (left->getType() != right->getType())
5085 {
5086 return false;
5087 }
5088 break;
5089 default:
5090 error(loc, "Invalid operation for structs", GetOperatorString(op));
5091 return false;
5092 }
5093 }
5094
Olli Etuaho94050052017-05-08 14:17:44 +03005095 if (left->isInterfaceBlock() || right->isInterfaceBlock())
5096 {
5097 switch (op)
5098 {
5099 case EOpIndexDirectInterfaceBlock:
5100 ASSERT(left->getType().getInterfaceBlock());
5101 break;
5102 default:
5103 error(loc, "Invalid operation for interface blocks", GetOperatorString(op));
5104 return false;
5105 }
5106 }
5107
Kai Ninomiya57ea5332017-11-22 14:04:48 -08005108 if (left->isArray() != right->isArray())
Olli Etuahod6b14282015-03-17 14:31:35 +02005109 {
Kai Ninomiya57ea5332017-11-22 14:04:48 -08005110 error(loc, "array / non-array mismatch", GetOperatorString(op));
5111 return false;
5112 }
5113
5114 if (left->isArray())
5115 {
5116 ASSERT(right->isArray());
Jamie Madill6e06b1f2015-05-14 10:01:17 -04005117 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02005118 {
5119 error(loc, "Invalid operation for arrays", GetOperatorString(op));
5120 return false;
5121 }
5122
Olli Etuahoe79904c2015-03-18 16:56:42 +02005123 switch (op)
5124 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04005125 case EOpEqual:
5126 case EOpNotEqual:
5127 case EOpAssign:
5128 case EOpInitialize:
5129 break;
5130 default:
5131 error(loc, "Invalid operation for arrays", GetOperatorString(op));
5132 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02005133 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03005134 // At this point, size of implicitly sized arrays should be resolved.
Kai Ninomiya57ea5332017-11-22 14:04:48 -08005135 if (*left->getType().getArraySizes() != *right->getType().getArraySizes())
Olli Etuahoe79904c2015-03-18 16:56:42 +02005136 {
5137 error(loc, "array size mismatch", GetOperatorString(op));
5138 return false;
5139 }
Olli Etuahod6b14282015-03-17 14:31:35 +02005140 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02005141
5142 // Check ops which require integer / ivec parameters
5143 bool isBitShift = false;
5144 switch (op)
5145 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04005146 case EOpBitShiftLeft:
5147 case EOpBitShiftRight:
5148 case EOpBitShiftLeftAssign:
5149 case EOpBitShiftRightAssign:
5150 // Unsigned can be bit-shifted by signed and vice versa, but we need to
5151 // check that the basic type is an integer type.
5152 isBitShift = true;
5153 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
5154 {
5155 return false;
5156 }
5157 break;
5158 case EOpBitwiseAnd:
5159 case EOpBitwiseXor:
5160 case EOpBitwiseOr:
5161 case EOpBitwiseAndAssign:
5162 case EOpBitwiseXorAssign:
5163 case EOpBitwiseOrAssign:
5164 // It is enough to check the type of only one operand, since later it
5165 // is checked that the operand types match.
5166 if (!IsInteger(left->getBasicType()))
5167 {
5168 return false;
5169 }
5170 break;
5171 default:
5172 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02005173 }
5174
5175 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
5176 // So the basic type should usually match.
5177 if (!isBitShift && left->getBasicType() != right->getBasicType())
5178 {
5179 return false;
5180 }
5181
Olli Etuaho63e1ec52016-08-18 22:05:12 +03005182 // Check that:
5183 // 1. Type sizes match exactly on ops that require that.
5184 // 2. Restrictions for structs that contain arrays or samplers are respected.
5185 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
Jamie Madillb98c3a82015-07-23 14:26:04 -04005186 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02005187 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04005188 case EOpAssign:
5189 case EOpInitialize:
5190 case EOpEqual:
5191 case EOpNotEqual:
5192 // ESSL 1.00 sections 5.7, 5.8, 5.9
5193 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
5194 {
5195 error(loc, "undefined operation for structs containing arrays",
5196 GetOperatorString(op));
5197 return false;
5198 }
5199 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
5200 // we interpret the spec so that this extends to structs containing samplers,
5201 // similarly to ESSL 1.00 spec.
5202 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
5203 left->getType().isStructureContainingSamplers())
5204 {
5205 error(loc, "undefined operation for structs containing samplers",
5206 GetOperatorString(op));
5207 return false;
5208 }
Martin Radev2cc85b32016-08-05 16:22:53 +03005209
Olli Etuahoe1805592017-01-02 16:41:20 +00005210 if ((left->getNominalSize() != right->getNominalSize()) ||
5211 (left->getSecondarySize() != right->getSecondarySize()))
5212 {
5213 error(loc, "dimension mismatch", GetOperatorString(op));
5214 return false;
5215 }
5216 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04005217 case EOpLessThan:
5218 case EOpGreaterThan:
5219 case EOpLessThanEqual:
5220 case EOpGreaterThanEqual:
Olli Etuahoe1805592017-01-02 16:41:20 +00005221 if (!left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04005222 {
Olli Etuahoe1805592017-01-02 16:41:20 +00005223 error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
Jamie Madillb98c3a82015-07-23 14:26:04 -04005224 return false;
5225 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03005226 break;
5227 case EOpAdd:
5228 case EOpSub:
5229 case EOpDiv:
5230 case EOpIMod:
5231 case EOpBitShiftLeft:
5232 case EOpBitShiftRight:
5233 case EOpBitwiseAnd:
5234 case EOpBitwiseXor:
5235 case EOpBitwiseOr:
5236 case EOpAddAssign:
5237 case EOpSubAssign:
5238 case EOpDivAssign:
5239 case EOpIModAssign:
5240 case EOpBitShiftLeftAssign:
5241 case EOpBitShiftRightAssign:
5242 case EOpBitwiseAndAssign:
5243 case EOpBitwiseXorAssign:
5244 case EOpBitwiseOrAssign:
5245 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
5246 {
5247 return false;
5248 }
5249
5250 // Are the sizes compatible?
5251 if (left->getNominalSize() != right->getNominalSize() ||
5252 left->getSecondarySize() != right->getSecondarySize())
5253 {
5254 // If the nominal sizes of operands do not match:
5255 // One of them must be a scalar.
5256 if (!left->isScalar() && !right->isScalar())
5257 return false;
5258
5259 // In the case of compound assignment other than multiply-assign,
5260 // the right side needs to be a scalar. Otherwise a vector/matrix
5261 // would be assigned to a scalar. A scalar can't be shifted by a
5262 // vector either.
5263 if (!right->isScalar() &&
5264 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
5265 return false;
5266 }
5267 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04005268 default:
5269 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02005270 }
5271
Olli Etuahod6b14282015-03-17 14:31:35 +02005272 return true;
5273}
5274
Olli Etuaho1dded802016-08-18 18:13:13 +03005275bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
5276 const TType &left,
5277 const TType &right)
5278{
5279 switch (op)
5280 {
5281 case EOpMul:
5282 case EOpMulAssign:
5283 return left.getNominalSize() == right.getNominalSize() &&
5284 left.getSecondarySize() == right.getSecondarySize();
5285 case EOpVectorTimesScalar:
5286 return true;
5287 case EOpVectorTimesScalarAssign:
5288 ASSERT(!left.isMatrix() && !right.isMatrix());
5289 return left.isVector() && !right.isVector();
5290 case EOpVectorTimesMatrix:
5291 return left.getNominalSize() == right.getRows();
5292 case EOpVectorTimesMatrixAssign:
5293 ASSERT(!left.isMatrix() && right.isMatrix());
5294 return left.isVector() && left.getNominalSize() == right.getRows() &&
5295 left.getNominalSize() == right.getCols();
5296 case EOpMatrixTimesVector:
5297 return left.getCols() == right.getNominalSize();
5298 case EOpMatrixTimesScalar:
5299 return true;
5300 case EOpMatrixTimesScalarAssign:
5301 ASSERT(left.isMatrix() && !right.isMatrix());
5302 return !right.isVector();
5303 case EOpMatrixTimesMatrix:
5304 return left.getCols() == right.getRows();
5305 case EOpMatrixTimesMatrixAssign:
5306 ASSERT(left.isMatrix() && right.isMatrix());
5307 // We need to check two things:
5308 // 1. The matrix multiplication step is valid.
5309 // 2. The result will have the same number of columns as the lvalue.
5310 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
5311
5312 default:
5313 UNREACHABLE();
5314 return false;
5315 }
5316}
5317
Jamie Madillb98c3a82015-07-23 14:26:04 -04005318TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
5319 TIntermTyped *left,
5320 TIntermTyped *right,
5321 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02005322{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02005323 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02005324 return nullptr;
5325
Olli Etuahofc1806e2015-03-17 13:03:11 +02005326 switch (op)
5327 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04005328 case EOpEqual:
5329 case EOpNotEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04005330 case EOpLessThan:
5331 case EOpGreaterThan:
5332 case EOpLessThanEqual:
5333 case EOpGreaterThanEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04005334 break;
5335 case EOpLogicalOr:
5336 case EOpLogicalXor:
5337 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03005338 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
5339 !right->getType().getStruct());
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00005340 if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04005341 {
5342 return nullptr;
5343 }
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00005344 // Basic types matching should have been already checked.
5345 ASSERT(right->getBasicType() == EbtBool);
Jamie Madillb98c3a82015-07-23 14:26:04 -04005346 break;
5347 case EOpAdd:
5348 case EOpSub:
5349 case EOpDiv:
5350 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03005351 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
5352 !right->getType().getStruct());
5353 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04005354 {
5355 return nullptr;
5356 }
5357 break;
5358 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03005359 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
5360 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04005361 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03005362 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04005363 {
5364 return nullptr;
5365 }
5366 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04005367 default:
5368 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02005369 }
5370
Olli Etuaho1dded802016-08-18 18:13:13 +03005371 if (op == EOpMul)
5372 {
5373 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
5374 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
5375 {
5376 return nullptr;
5377 }
5378 }
5379
Olli Etuaho3fdec912016-08-18 15:08:06 +03005380 TIntermBinary *node = new TIntermBinary(op, left, right);
Olli Etuaho94bbed12018-03-20 14:44:53 +02005381 ASSERT(op != EOpAssign);
5382 markStaticReadIfSymbol(left);
5383 markStaticReadIfSymbol(right);
Olli Etuaho3fdec912016-08-18 15:08:06 +03005384 node->setLine(loc);
Olli Etuahoea22b7a2018-01-04 17:09:11 +02005385 return expressionOrFoldedResult(node);
Olli Etuahofc1806e2015-03-17 13:03:11 +02005386}
5387
Jamie Madillb98c3a82015-07-23 14:26:04 -04005388TIntermTyped *TParseContext::addBinaryMath(TOperator op,
5389 TIntermTyped *left,
5390 TIntermTyped *right,
5391 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02005392{
Olli Etuahofc1806e2015-03-17 13:03:11 +02005393 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02005394 if (node == 0)
5395 {
Olli Etuaho72e35892018-06-20 11:43:08 +03005396 binaryOpError(loc, GetOperatorString(op), left->getType(), right->getType());
Olli Etuaho09b22472015-02-11 11:47:26 +02005397 return left;
5398 }
5399 return node;
5400}
5401
Jamie Madillb98c3a82015-07-23 14:26:04 -04005402TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
5403 TIntermTyped *left,
5404 TIntermTyped *right,
5405 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02005406{
Olli Etuahofc1806e2015-03-17 13:03:11 +02005407 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho56229f12017-07-10 14:16:33 +03005408 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02005409 {
Olli Etuaho72e35892018-06-20 11:43:08 +03005410 binaryOpError(loc, GetOperatorString(op), left->getType(), right->getType());
Olli Etuaho3ec75682017-07-05 17:02:55 +03005411 node = CreateBoolNode(false);
Olli Etuaho56229f12017-07-10 14:16:33 +03005412 node->setLine(loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02005413 }
5414 return node;
5415}
5416
Jamie Madillb98c3a82015-07-23 14:26:04 -04005417TIntermTyped *TParseContext::addAssign(TOperator op,
5418 TIntermTyped *left,
5419 TIntermTyped *right,
5420 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02005421{
Olli Etuahocce89652017-06-19 16:04:09 +03005422 checkCanBeLValue(loc, "assign", left);
Olli Etuaho7b7d2e62018-03-23 16:37:36 +02005423 TIntermBinary *node = nullptr;
5424 if (binaryOpCommonCheck(op, left, right, loc))
5425 {
5426 if (op == EOpMulAssign)
5427 {
5428 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
5429 if (isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
5430 {
5431 node = new TIntermBinary(op, left, right);
5432 }
5433 }
5434 else
5435 {
5436 node = new TIntermBinary(op, left, right);
5437 }
5438 }
Olli Etuahod6b14282015-03-17 14:31:35 +02005439 if (node == nullptr)
5440 {
Olli Etuaho72e35892018-06-20 11:43:08 +03005441 assignError(loc, "assign", left->getType(), right->getType());
Olli Etuahod6b14282015-03-17 14:31:35 +02005442 return left;
5443 }
Olli Etuaho94bbed12018-03-20 14:44:53 +02005444 if (op != EOpAssign)
5445 {
5446 markStaticReadIfSymbol(left);
5447 }
5448 markStaticReadIfSymbol(right);
Olli Etuaho7b7d2e62018-03-23 16:37:36 +02005449 node->setLine(loc);
Olli Etuahod6b14282015-03-17 14:31:35 +02005450 return node;
5451}
5452
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02005453TIntermTyped *TParseContext::addComma(TIntermTyped *left,
5454 TIntermTyped *right,
5455 const TSourceLoc &loc)
5456{
Corentin Wallez0d959252016-07-12 17:26:32 -04005457 // WebGL2 section 5.26, the following results in an error:
5458 // "Sequence operator applied to void, arrays, or structs containing arrays"
Jamie Madilld7b1ab52016-12-12 14:42:19 -05005459 if (mShaderSpec == SH_WEBGL2_SPEC &&
5460 (left->isArray() || left->getBasicType() == EbtVoid ||
5461 left->getType().isStructureContainingArrays() || right->isArray() ||
5462 right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
Corentin Wallez0d959252016-07-12 17:26:32 -04005463 {
5464 error(loc,
5465 "sequence operator is not allowed for void, arrays, or structs containing arrays",
5466 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04005467 }
5468
Olli Etuaho0e99b7a2018-01-12 12:05:48 +02005469 TIntermBinary *commaNode = TIntermBinary::CreateComma(left, right, mShaderVersion);
Olli Etuaho94bbed12018-03-20 14:44:53 +02005470 markStaticReadIfSymbol(left);
5471 markStaticReadIfSymbol(right);
5472 commaNode->setLine(loc);
Olli Etuaho765924f2018-01-04 12:48:36 +02005473
5474 return expressionOrFoldedResult(commaNode);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02005475}
5476
Olli Etuaho49300862015-02-20 14:54:49 +02005477TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
5478{
5479 switch (op)
5480 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04005481 case EOpContinue:
5482 if (mLoopNestingLevel <= 0)
5483 {
5484 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04005485 }
5486 break;
5487 case EOpBreak:
5488 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
5489 {
5490 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04005491 }
5492 break;
5493 case EOpReturn:
5494 if (mCurrentFunctionType->getBasicType() != EbtVoid)
5495 {
5496 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04005497 }
5498 break;
Olli Etuahocce89652017-06-19 16:04:09 +03005499 case EOpKill:
5500 if (mShaderType != GL_FRAGMENT_SHADER)
5501 {
5502 error(loc, "discard supported in fragment shaders only", "discard");
5503 }
5504 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04005505 default:
Olli Etuahocce89652017-06-19 16:04:09 +03005506 UNREACHABLE();
Jamie Madillb98c3a82015-07-23 14:26:04 -04005507 break;
Olli Etuaho49300862015-02-20 14:54:49 +02005508 }
Olli Etuahocce89652017-06-19 16:04:09 +03005509 return addBranch(op, nullptr, loc);
Olli Etuaho49300862015-02-20 14:54:49 +02005510}
5511
Jamie Madillb98c3a82015-07-23 14:26:04 -04005512TIntermBranch *TParseContext::addBranch(TOperator op,
Olli Etuahocce89652017-06-19 16:04:09 +03005513 TIntermTyped *expression,
Jamie Madillb98c3a82015-07-23 14:26:04 -04005514 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02005515{
Olli Etuahocce89652017-06-19 16:04:09 +03005516 if (expression != nullptr)
Olli Etuaho49300862015-02-20 14:54:49 +02005517 {
Olli Etuaho94bbed12018-03-20 14:44:53 +02005518 markStaticReadIfSymbol(expression);
Olli Etuahocce89652017-06-19 16:04:09 +03005519 ASSERT(op == EOpReturn);
5520 mFunctionReturnsValue = true;
5521 if (mCurrentFunctionType->getBasicType() == EbtVoid)
5522 {
5523 error(loc, "void function cannot return a value", "return");
5524 }
5525 else if (*mCurrentFunctionType != expression->getType())
5526 {
5527 error(loc, "function return is not matching type:", "return");
5528 }
Olli Etuaho49300862015-02-20 14:54:49 +02005529 }
Olli Etuahocce89652017-06-19 16:04:09 +03005530 TIntermBranch *node = new TIntermBranch(op, expression);
5531 node->setLine(loc);
5532 return node;
Olli Etuaho49300862015-02-20 14:54:49 +02005533}
5534
Olli Etuaho94bbed12018-03-20 14:44:53 +02005535void TParseContext::appendStatement(TIntermBlock *block, TIntermNode *statement)
5536{
5537 if (statement != nullptr)
5538 {
5539 markStaticReadIfSymbol(statement);
5540 block->appendStatement(statement);
5541 }
5542}
5543
Martin Radev84aa2dc2017-09-11 15:51:02 +03005544void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
5545{
5546 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005547 const TFunction *func = functionCall->getFunction();
5548 if (BuiltInGroup::isTextureGather(func))
Martin Radev84aa2dc2017-09-11 15:51:02 +03005549 {
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005550 bool isTextureGatherOffset = BuiltInGroup::isTextureGatherOffset(func);
Martin Radev84aa2dc2017-09-11 15:51:02 +03005551 TIntermNode *componentNode = nullptr;
5552 TIntermSequence *arguments = functionCall->getSequence();
5553 ASSERT(arguments->size() >= 2u && arguments->size() <= 4u);
5554 const TIntermTyped *sampler = arguments->front()->getAsTyped();
5555 ASSERT(sampler != nullptr);
5556 switch (sampler->getBasicType())
5557 {
5558 case EbtSampler2D:
5559 case EbtISampler2D:
5560 case EbtUSampler2D:
5561 case EbtSampler2DArray:
5562 case EbtISampler2DArray:
5563 case EbtUSampler2DArray:
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005564 if ((!isTextureGatherOffset && arguments->size() == 3u) ||
Martin Radev84aa2dc2017-09-11 15:51:02 +03005565 (isTextureGatherOffset && arguments->size() == 4u))
5566 {
5567 componentNode = arguments->back();
5568 }
5569 break;
5570 case EbtSamplerCube:
5571 case EbtISamplerCube:
5572 case EbtUSamplerCube:
5573 ASSERT(!isTextureGatherOffset);
5574 if (arguments->size() == 3u)
5575 {
5576 componentNode = arguments->back();
5577 }
5578 break;
5579 case EbtSampler2DShadow:
5580 case EbtSampler2DArrayShadow:
5581 case EbtSamplerCubeShadow:
5582 break;
5583 default:
5584 UNREACHABLE();
5585 break;
5586 }
5587 if (componentNode)
5588 {
5589 const TIntermConstantUnion *componentConstantUnion =
5590 componentNode->getAsConstantUnion();
5591 if (componentNode->getAsTyped()->getQualifier() != EvqConst || !componentConstantUnion)
5592 {
5593 error(functionCall->getLine(), "Texture component must be a constant expression",
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005594 func->name());
Martin Radev84aa2dc2017-09-11 15:51:02 +03005595 }
5596 else
5597 {
5598 int component = componentConstantUnion->getIConst(0);
5599 if (component < 0 || component > 3)
5600 {
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005601 error(functionCall->getLine(), "Component must be in the range [0;3]",
5602 func->name());
Martin Radev84aa2dc2017-09-11 15:51:02 +03005603 }
5604 }
5605 }
5606 }
5607}
5608
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005609void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
5610{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08005611 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005612 const TFunction *func = functionCall->getFunction();
Jamie Madill50cf2be2018-06-15 09:46:57 -04005613 TIntermNode *offset = nullptr;
5614 TIntermSequence *arguments = functionCall->getSequence();
Martin Radev84aa2dc2017-09-11 15:51:02 +03005615 bool useTextureGatherOffsetConstraints = false;
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005616 if (BuiltInGroup::isTextureOffsetNoBias(func))
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005617 {
5618 offset = arguments->back();
5619 }
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005620 else if (BuiltInGroup::isTextureOffsetBias(func))
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005621 {
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005622 // A bias parameter follows the offset parameter.
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005623 ASSERT(arguments->size() >= 3);
5624 offset = (*arguments)[2];
5625 }
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005626 else if (BuiltInGroup::isTextureGatherOffset(func))
Martin Radev84aa2dc2017-09-11 15:51:02 +03005627 {
5628 ASSERT(arguments->size() >= 3u);
5629 const TIntermTyped *sampler = arguments->front()->getAsTyped();
5630 ASSERT(sampler != nullptr);
5631 switch (sampler->getBasicType())
5632 {
5633 case EbtSampler2D:
5634 case EbtISampler2D:
5635 case EbtUSampler2D:
5636 case EbtSampler2DArray:
5637 case EbtISampler2DArray:
5638 case EbtUSampler2DArray:
5639 offset = (*arguments)[2];
5640 break;
5641 case EbtSampler2DShadow:
5642 case EbtSampler2DArrayShadow:
5643 offset = (*arguments)[3];
5644 break;
5645 default:
5646 UNREACHABLE();
5647 break;
5648 }
5649 useTextureGatherOffsetConstraints = true;
5650 }
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005651 if (offset != nullptr)
5652 {
5653 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
5654 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
5655 {
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005656 error(functionCall->getLine(), "Texture offset must be a constant expression",
5657 func->name());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005658 }
5659 else
5660 {
5661 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
5662 size_t size = offsetConstantUnion->getType().getObjectSize();
Olli Etuahoea22b7a2018-01-04 17:09:11 +02005663 const TConstantUnion *values = offsetConstantUnion->getConstantValue();
Martin Radev84aa2dc2017-09-11 15:51:02 +03005664 int minOffsetValue = useTextureGatherOffsetConstraints ? mMinProgramTextureGatherOffset
5665 : mMinProgramTexelOffset;
5666 int maxOffsetValue = useTextureGatherOffsetConstraints ? mMaxProgramTextureGatherOffset
5667 : mMaxProgramTexelOffset;
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005668 for (size_t i = 0u; i < size; ++i)
5669 {
5670 int offsetValue = values[i].getIConst();
Martin Radev84aa2dc2017-09-11 15:51:02 +03005671 if (offsetValue > maxOffsetValue || offsetValue < minOffsetValue)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005672 {
Jonah Ryan-Davisf563fdc2019-01-31 13:53:59 -05005673 std::stringstream tokenStream = sh::InitializeStream<std::stringstream>();
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005674 tokenStream << offsetValue;
5675 std::string token = tokenStream.str();
5676 error(offset->getLine(), "Texture offset value out of valid range",
5677 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005678 }
5679 }
5680 }
5681 }
5682}
5683
Jiajia Qina3106c52017-11-03 09:39:39 +08005684void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall)
5685{
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005686 const TFunction *func = functionCall->getFunction();
5687 if (BuiltInGroup::isAtomicMemory(func))
Jiajia Qina3106c52017-11-03 09:39:39 +08005688 {
Jiawei Shaoa6a78422018-06-28 08:32:54 +08005689 ASSERT(IsAtomicFunction(functionCall->getOp()));
Jiajia Qina3106c52017-11-03 09:39:39 +08005690 TIntermSequence *arguments = functionCall->getSequence();
5691 TIntermTyped *memNode = (*arguments)[0]->getAsTyped();
5692
5693 if (IsBufferOrSharedVariable(memNode))
5694 {
5695 return;
5696 }
5697
5698 while (memNode->getAsBinaryNode())
5699 {
5700 memNode = memNode->getAsBinaryNode()->getLeft();
5701 if (IsBufferOrSharedVariable(memNode))
5702 {
5703 return;
5704 }
5705 }
5706
5707 error(memNode->getLine(),
5708 "The value passed to the mem argument of an atomic memory function does not "
5709 "correspond to a buffer or shared variable.",
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005710 func->name());
Jiajia Qina3106c52017-11-03 09:39:39 +08005711 }
5712}
5713
Martin Radev2cc85b32016-08-05 16:22:53 +03005714// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
5715void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
5716{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08005717 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Martin Radev2cc85b32016-08-05 16:22:53 +03005718
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005719 const TFunction *func = functionCall->getFunction();
5720
5721 if (BuiltInGroup::isImage(func))
Martin Radev2cc85b32016-08-05 16:22:53 +03005722 {
5723 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuaho485eefd2017-02-14 17:40:06 +00005724 TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
Martin Radev2cc85b32016-08-05 16:22:53 +03005725
Olli Etuaho485eefd2017-02-14 17:40:06 +00005726 const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
Martin Radev2cc85b32016-08-05 16:22:53 +03005727
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005728 if (BuiltInGroup::isImageStore(func))
Martin Radev2cc85b32016-08-05 16:22:53 +03005729 {
5730 if (memoryQualifier.readonly)
5731 {
5732 error(imageNode->getLine(),
5733 "'imageStore' cannot be used with images qualified as 'readonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005734 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03005735 }
5736 }
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005737 else if (BuiltInGroup::isImageLoad(func))
Martin Radev2cc85b32016-08-05 16:22:53 +03005738 {
5739 if (memoryQualifier.writeonly)
5740 {
5741 error(imageNode->getLine(),
5742 "'imageLoad' cannot be used with images qualified as 'writeonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005743 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03005744 }
5745 }
5746 }
5747}
5748
5749// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
5750void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
5751 const TFunction *functionDefinition,
5752 const TIntermAggregate *functionCall)
5753{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08005754 ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
Martin Radev2cc85b32016-08-05 16:22:53 +03005755
5756 const TIntermSequence &arguments = *functionCall->getSequence();
5757
5758 ASSERT(functionDefinition->getParamCount() == arguments.size());
5759
5760 for (size_t i = 0; i < arguments.size(); ++i)
5761 {
Olli Etuaho485eefd2017-02-14 17:40:06 +00005762 TIntermTyped *typedArgument = arguments[i]->getAsTyped();
5763 const TType &functionArgumentType = typedArgument->getType();
Olli Etuahod4bd9632018-03-08 16:32:44 +02005764 const TType &functionParameterType = functionDefinition->getParam(i)->getType();
Martin Radev2cc85b32016-08-05 16:22:53 +03005765 ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
5766
5767 if (IsImage(functionArgumentType.getBasicType()))
5768 {
5769 const TMemoryQualifier &functionArgumentMemoryQualifier =
5770 functionArgumentType.getMemoryQualifier();
5771 const TMemoryQualifier &functionParameterMemoryQualifier =
5772 functionParameterType.getMemoryQualifier();
5773 if (functionArgumentMemoryQualifier.readonly &&
5774 !functionParameterMemoryQualifier.readonly)
5775 {
5776 error(functionCall->getLine(),
5777 "Function call discards the 'readonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005778 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03005779 }
5780
5781 if (functionArgumentMemoryQualifier.writeonly &&
5782 !functionParameterMemoryQualifier.writeonly)
5783 {
5784 error(functionCall->getLine(),
5785 "Function call discards the 'writeonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005786 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03005787 }
Martin Radev049edfa2016-11-11 14:35:37 +02005788
5789 if (functionArgumentMemoryQualifier.coherent &&
5790 !functionParameterMemoryQualifier.coherent)
5791 {
5792 error(functionCall->getLine(),
5793 "Function call discards the 'coherent' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005794 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02005795 }
5796
5797 if (functionArgumentMemoryQualifier.volatileQualifier &&
5798 !functionParameterMemoryQualifier.volatileQualifier)
5799 {
5800 error(functionCall->getLine(),
5801 "Function call discards the 'volatile' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005802 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02005803 }
Martin Radev2cc85b32016-08-05 16:22:53 +03005804 }
5805 }
5806}
5807
Olli Etuaho95ed1942018-02-01 14:01:19 +02005808TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunctionLookup *fnCall, const TSourceLoc &loc)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005809{
Olli Etuaho95ed1942018-02-01 14:01:19 +02005810 if (fnCall->thisNode() != nullptr)
5811 {
5812 return addMethod(fnCall, loc);
5813 }
5814 if (fnCall->isConstructor())
5815 {
5816 return addConstructor(fnCall, loc);
5817 }
5818 return addNonConstructorFunctionCall(fnCall, loc);
Olli Etuaho72d10202017-01-19 15:58:30 +00005819}
5820
Olli Etuaho95ed1942018-02-01 14:01:19 +02005821TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc)
Olli Etuaho72d10202017-01-19 15:58:30 +00005822{
Olli Etuaho95ed1942018-02-01 14:01:19 +02005823 TIntermTyped *thisNode = fnCall->thisNode();
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005824 // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
5825 // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
5826 // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
Olli Etuahoae4dbf32017-12-08 20:49:00 +01005827 // So accessing fnCall->name() below is safe.
Olli Etuaho95ed1942018-02-01 14:01:19 +02005828 if (fnCall->name() != "length")
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005829 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02005830 error(loc, "invalid method", fnCall->name());
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005831 }
Olli Etuaho95ed1942018-02-01 14:01:19 +02005832 else if (!fnCall->arguments().empty())
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005833 {
5834 error(loc, "method takes no parameters", "length");
5835 }
Olli Etuaho95ed1942018-02-01 14:01:19 +02005836 else if (!thisNode->isArray())
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005837 {
5838 error(loc, "length can only be called on arrays", "length");
5839 }
Olli Etuaho95ed1942018-02-01 14:01:19 +02005840 else if (thisNode->getQualifier() == EvqPerVertexIn &&
Jiawei Shaod8105a02017-08-08 09:54:36 +08005841 mGeometryShaderInputPrimitiveType == EptUndefined)
5842 {
Jiawei Shaobd924af2017-11-16 15:28:04 +08005843 ASSERT(mShaderType == GL_GEOMETRY_SHADER_EXT);
Jiawei Shaod8105a02017-08-08 09:54:36 +08005844 error(loc, "missing input primitive declaration before calling length on gl_in", "length");
5845 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005846 else
5847 {
Olli Etuaho5fec7ab2018-04-04 11:58:33 +03005848 TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode, nullptr);
Qin Jiajia19f2f9e2018-12-07 15:10:48 +08005849 markStaticReadIfSymbol(thisNode);
Olli Etuahobb2bbfb2017-08-24 15:43:33 +03005850 node->setLine(loc);
5851 return node->fold(mDiagnostics);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005852 }
Olli Etuahobb2bbfb2017-08-24 15:43:33 +03005853 return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst));
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005854}
5855
Olli Etuaho95ed1942018-02-01 14:01:19 +02005856TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCall,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005857 const TSourceLoc &loc)
5858{
Olli Etuaho697bf652018-02-16 11:50:54 +02005859 // First check whether the function has been hidden by a variable name or struct typename by
5860 // using the symbol looked up in the lexical phase. If the function is not hidden, look for one
5861 // with a matching argument list.
5862 if (fnCall->symbol() != nullptr && !fnCall->symbol()->isFunction())
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005863 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02005864 error(loc, "function name expected", fnCall->name());
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005865 }
5866 else
5867 {
Olli Etuahoe80825e2018-02-16 10:24:53 +02005868 // There are no inner functions, so it's enough to look for user-defined functions in the
5869 // global scope.
Olli Etuaho697bf652018-02-16 11:50:54 +02005870 const TSymbol *symbol = symbolTable.findGlobal(fnCall->getMangledName());
Olli Etuahoe80825e2018-02-16 10:24:53 +02005871 if (symbol != nullptr)
5872 {
5873 // A user-defined function - could be an overloaded built-in as well.
5874 ASSERT(symbol->symbolType() == SymbolType::UserDefined);
5875 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
5876 TIntermAggregate *callNode =
5877 TIntermAggregate::CreateFunctionCall(*fnCandidate, &fnCall->arguments());
5878 callNode->setLine(loc);
5879 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
5880 functionCallRValueLValueErrorCheck(fnCandidate, callNode);
5881 return callNode;
5882 }
5883
5884 symbol = symbolTable.findBuiltIn(fnCall->getMangledName(), mShaderVersion);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005885 if (symbol == nullptr)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005886 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02005887 error(loc, "no matching overloaded function found", fnCall->name());
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005888 }
5889 else
5890 {
Olli Etuahoe80825e2018-02-16 10:24:53 +02005891 // A built-in function.
5892 ASSERT(symbol->symbolType() == SymbolType::BuiltIn);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005893 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
Olli Etuahoe80825e2018-02-16 10:24:53 +02005894
Olli Etuaho37b697e2018-01-29 12:19:27 +02005895 if (fnCandidate->extension() != TExtension::UNDEFINED)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005896 {
Olli Etuaho54a29ff2017-11-28 17:35:20 +02005897 checkCanUseExtension(loc, fnCandidate->extension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005898 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005899 TOperator op = fnCandidate->getBuiltInOp();
Olli Etuahoe80825e2018-02-16 10:24:53 +02005900 if (op != EOpCallBuiltInFunction)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005901 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005902 // A function call mapped to a built-in operation.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005903 if (fnCandidate->getParamCount() == 1)
5904 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005905 // Treat it like a built-in unary operator.
Olli Etuaho95ed1942018-02-01 14:01:19 +02005906 TIntermNode *unaryParamNode = fnCall->arguments().front();
Olli Etuaho5fec7ab2018-04-04 11:58:33 +03005907 TIntermTyped *callNode =
5908 createUnaryMath(op, unaryParamNode->getAsTyped(), loc, fnCandidate);
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08005909 ASSERT(callNode != nullptr);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005910 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005911 }
Jiawei Shaoa6a78422018-06-28 08:32:54 +08005912
Olli Etuahoe80825e2018-02-16 10:24:53 +02005913 TIntermAggregate *callNode =
5914 TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, &fnCall->arguments());
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005915 callNode->setLine(loc);
5916
Jiawei Shaoa6a78422018-06-28 08:32:54 +08005917 checkAtomicMemoryBuiltinFunctions(callNode);
5918
Olli Etuahoe80825e2018-02-16 10:24:53 +02005919 // Some built-in functions have out parameters too.
5920 functionCallRValueLValueErrorCheck(fnCandidate, callNode);
5921
5922 // See if we can constant fold a built-in. Note that this may be possible
5923 // even if it is not const-qualified.
5924 return callNode->fold(mDiagnostics);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005925 }
Olli Etuahoe80825e2018-02-16 10:24:53 +02005926
5927 // This is a built-in function with no op associated with it.
5928 TIntermAggregate *callNode =
5929 TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, &fnCall->arguments());
5930 callNode->setLine(loc);
5931 checkTextureOffsetConst(callNode);
5932 checkTextureGather(callNode);
5933 checkImageMemoryAccessForBuiltinFunctions(callNode);
Olli Etuahoe80825e2018-02-16 10:24:53 +02005934 functionCallRValueLValueErrorCheck(fnCandidate, callNode);
5935 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005936 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005937 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005938
5939 // Error message was already written. Put on a dummy node for error recovery.
Olli Etuaho3ec75682017-07-05 17:02:55 +03005940 return CreateZeroNode(TType(EbtFloat, EbpMedium, EvqConst));
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005941}
5942
Jamie Madillb98c3a82015-07-23 14:26:04 -04005943TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005944 TIntermTyped *trueExpression,
5945 TIntermTyped *falseExpression,
Olli Etuaho52901742015-04-15 13:42:45 +03005946 const TSourceLoc &loc)
5947{
Olli Etuaho56229f12017-07-10 14:16:33 +03005948 if (!checkIsScalarBool(loc, cond))
5949 {
5950 return falseExpression;
5951 }
Olli Etuaho52901742015-04-15 13:42:45 +03005952
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005953 if (trueExpression->getType() != falseExpression->getType())
Olli Etuaho52901742015-04-15 13:42:45 +03005954 {
Olli Etuaho72e35892018-06-20 11:43:08 +03005955 TInfoSinkBase reasonStream;
5956 reasonStream << "mismatching ternary operator operand types '" << trueExpression->getType()
5957 << " and '" << falseExpression->getType() << "'";
5958 error(loc, reasonStream.c_str(), "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005959 return falseExpression;
Olli Etuaho52901742015-04-15 13:42:45 +03005960 }
Olli Etuahode318b22016-10-25 16:18:25 +01005961 if (IsOpaqueType(trueExpression->getBasicType()))
5962 {
5963 // ESSL 1.00 section 4.1.7
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005964 // ESSL 3.00.6 section 4.1.7
Olli Etuahode318b22016-10-25 16:18:25 +01005965 // Opaque/sampler types are not allowed in most types of expressions, including ternary.
5966 // Note that structs containing opaque types don't need to be checked as structs are
5967 // forbidden below.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005968 error(loc, "ternary operator is not allowed for opaque types", "?:");
Olli Etuahode318b22016-10-25 16:18:25 +01005969 return falseExpression;
5970 }
5971
Jiajia Qinbc585152017-06-23 15:42:17 +08005972 if (cond->getMemoryQualifier().writeonly || trueExpression->getMemoryQualifier().writeonly ||
5973 falseExpression->getMemoryQualifier().writeonly)
5974 {
5975 error(loc, "ternary operator is not allowed for variables with writeonly", "?:");
5976 return falseExpression;
5977 }
5978
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005979 // ESSL 1.00.17 sections 5.2 and 5.7:
Olli Etuahoa2d53032015-04-15 14:14:44 +03005980 // Ternary operator is not among the operators allowed for structures/arrays.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005981 // ESSL 3.00.6 section 5.7:
5982 // Ternary operator support is optional for arrays. No certainty that it works across all
5983 // devices with struct either, so we err on the side of caution here. TODO (oetuaho@nvidia.com):
5984 // Would be nice to make the spec and implementation agree completely here.
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005985 if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
Olli Etuahoa2d53032015-04-15 14:14:44 +03005986 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005987 error(loc, "ternary operator is not allowed for structures or arrays", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005988 return falseExpression;
Olli Etuahoa2d53032015-04-15 14:14:44 +03005989 }
Olli Etuaho94050052017-05-08 14:17:44 +03005990 if (trueExpression->getBasicType() == EbtInterfaceBlock)
5991 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005992 error(loc, "ternary operator is not allowed for interface blocks", "?:");
Olli Etuaho94050052017-05-08 14:17:44 +03005993 return falseExpression;
5994 }
5995
Corentin Wallez0d959252016-07-12 17:26:32 -04005996 // WebGL2 section 5.26, the following results in an error:
5997 // "Ternary operator applied to void, arrays, or structs containing arrays"
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005998 if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
Corentin Wallez0d959252016-07-12 17:26:32 -04005999 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03006000 error(loc, "ternary operator is not allowed for void", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03006001 return falseExpression;
Corentin Wallez0d959252016-07-12 17:26:32 -04006002 }
6003
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03006004 TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression);
Olli Etuaho94bbed12018-03-20 14:44:53 +02006005 markStaticReadIfSymbol(cond);
6006 markStaticReadIfSymbol(trueExpression);
6007 markStaticReadIfSymbol(falseExpression);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03006008 node->setLine(loc);
Olli Etuaho765924f2018-01-04 12:48:36 +02006009 return expressionOrFoldedResult(node);
Olli Etuaho52901742015-04-15 13:42:45 +03006010}
Olli Etuaho49300862015-02-20 14:54:49 +02006011
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00006012//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00006013// Parse an array of strings using yyparse.
6014//
6015// Returns 0 for success.
6016//
Jamie Madillb98c3a82015-07-23 14:26:04 -04006017int PaParseStrings(size_t count,
6018 const char *const string[],
6019 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05306020 TParseContext *context)
6021{
Yunchao He4f285442017-04-21 12:15:49 +08006022 if ((count == 0) || (string == nullptr))
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00006023 return 1;
6024
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00006025 if (glslang_initialize(context))
6026 return 1;
6027
alokp@chromium.org408c45e2012-04-05 15:54:43 +00006028 int error = glslang_scan(count, string, length, context);
6029 if (!error)
6030 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00006031
alokp@chromium.org73bc2982012-06-19 18:48:05 +00006032 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00006033
alokp@chromium.org6b495712012-06-29 00:06:58 +00006034 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00006035}
Jamie Madill45bcc782016-11-07 13:58:48 -05006036
6037} // namespace sh