blob: 19d0fda45e48ff361ca4a3ad12dd93a25e900e9e [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
Mingyu Huebab6702019-04-19 14:36:45 -0700222bool TParseContext::anyMultiviewExtensionAvailable()
223{
224 return isExtensionEnabled(TExtension::OVR_multiview) ||
225 isExtensionEnabled(TExtension::OVR_multiview2);
226}
227
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300228bool TParseContext::parseVectorFields(const TSourceLoc &line,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200229 const ImmutableString &compString,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400230 int vecSize,
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300231 TVector<int> *fieldOffsets)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000232{
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300233 ASSERT(fieldOffsets);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200234 size_t fieldCount = compString.length();
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300235 if (fieldCount > 4u)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530236 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200237 error(line, "illegal vector field selection", compString);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000238 return false;
239 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300240 fieldOffsets->resize(fieldCount);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241
Jamie Madillb98c3a82015-07-23 14:26:04 -0400242 enum
243 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000244 exyzw,
245 ergba,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000246 estpq
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000247 } fieldSet[4];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000248
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300249 for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530250 {
251 switch (compString[i])
252 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400253 case 'x':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300254 (*fieldOffsets)[i] = 0;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400255 fieldSet[i] = exyzw;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400256 break;
257 case 'r':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300258 (*fieldOffsets)[i] = 0;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400259 fieldSet[i] = ergba;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400260 break;
261 case 's':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300262 (*fieldOffsets)[i] = 0;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400263 fieldSet[i] = estpq;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400264 break;
265 case 'y':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300266 (*fieldOffsets)[i] = 1;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400267 fieldSet[i] = exyzw;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400268 break;
269 case 'g':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300270 (*fieldOffsets)[i] = 1;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400271 fieldSet[i] = ergba;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400272 break;
273 case 't':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300274 (*fieldOffsets)[i] = 1;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400275 fieldSet[i] = estpq;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400276 break;
277 case 'z':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300278 (*fieldOffsets)[i] = 2;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400279 fieldSet[i] = exyzw;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400280 break;
281 case 'b':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300282 (*fieldOffsets)[i] = 2;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400283 fieldSet[i] = ergba;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400284 break;
285 case 'p':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300286 (*fieldOffsets)[i] = 2;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400287 fieldSet[i] = estpq;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400288 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530289
Jamie Madillb98c3a82015-07-23 14:26:04 -0400290 case 'w':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300291 (*fieldOffsets)[i] = 3;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400292 fieldSet[i] = exyzw;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400293 break;
294 case 'a':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300295 (*fieldOffsets)[i] = 3;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400296 fieldSet[i] = ergba;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400297 break;
298 case 'q':
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300299 (*fieldOffsets)[i] = 3;
Jamie Madill50cf2be2018-06-15 09:46:57 -0400300 fieldSet[i] = estpq;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400301 break;
302 default:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200303 error(line, "illegal vector field selection", compString);
Jamie Madillb98c3a82015-07-23 14:26:04 -0400304 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000305 }
306 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000307
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300308 for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530309 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +0300310 if ((*fieldOffsets)[i] >= vecSize)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530311 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200312 error(line, "vector field selection out of range", compString);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000313 return false;
314 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000315
Arun Patole7e7e68d2015-05-22 12:02:25 +0530316 if (i > 0)
317 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400318 if (fieldSet[i] != fieldSet[i - 1])
Arun Patole7e7e68d2015-05-22 12:02:25 +0530319 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200320 error(line, "illegal - vector component fields not from the same set", compString);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000321 return false;
322 }
323 }
324 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000325
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000326 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000327}
328
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000329///////////////////////////////////////////////////////////////////////
330//
331// Errors
332//
333////////////////////////////////////////////////////////////////////////
334
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000335//
336// Used by flex/bison to output all syntax and parsing errors.
337//
Olli Etuaho4de340a2016-12-16 09:32:03 +0000338void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000340 mDiagnostics->error(loc, reason, token);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341}
342
Olli Etuahofbb1c792018-01-19 16:26:59 +0200343void TParseContext::error(const TSourceLoc &loc, const char *reason, const ImmutableString &token)
344{
345 mDiagnostics->error(loc, reason, token.data());
346}
347
Olli Etuaho4de340a2016-12-16 09:32:03 +0000348void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530349{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000350 mDiagnostics->warning(loc, reason, token);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +0000351}
352
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200353void TParseContext::outOfRangeError(bool isError,
354 const TSourceLoc &loc,
355 const char *reason,
Olli Etuaho4de340a2016-12-16 09:32:03 +0000356 const char *token)
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200357{
358 if (isError)
359 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000360 error(loc, reason, token);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200361 }
362 else
363 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000364 warning(loc, reason, token);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200365 }
366}
367
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000368//
369// Same error message for all places assignments don't work.
370//
Olli Etuaho72e35892018-06-20 11:43:08 +0300371void TParseContext::assignError(const TSourceLoc &line,
372 const char *op,
373 const TType &left,
374 const TType &right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000375{
Olli Etuaho72e35892018-06-20 11:43:08 +0300376 TInfoSinkBase reasonStream;
Olli Etuaho4de340a2016-12-16 09:32:03 +0000377 reasonStream << "cannot convert from '" << right << "' to '" << left << "'";
Olli Etuaho72e35892018-06-20 11:43:08 +0300378 error(line, reasonStream.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000379}
380
381//
382// Same error message for all places unary operations don't work.
383//
Olli Etuaho72e35892018-06-20 11:43:08 +0300384void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, const TType &operand)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000385{
Olli Etuaho72e35892018-06-20 11:43:08 +0300386 TInfoSinkBase reasonStream;
Olli Etuaho4de340a2016-12-16 09:32:03 +0000387 reasonStream << "wrong operand type - no operation '" << op
388 << "' exists that takes an operand of type " << operand
389 << " (or there is no acceptable conversion)";
Olli Etuaho72e35892018-06-20 11:43:08 +0300390 error(line, reasonStream.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000391}
392
393//
394// Same error message for all binary operations don't work.
395//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400396void TParseContext::binaryOpError(const TSourceLoc &line,
397 const char *op,
Olli Etuaho72e35892018-06-20 11:43:08 +0300398 const TType &left,
399 const TType &right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000400{
Olli Etuaho72e35892018-06-20 11:43:08 +0300401 TInfoSinkBase reasonStream;
Olli Etuaho4de340a2016-12-16 09:32:03 +0000402 reasonStream << "wrong operand types - no operation '" << op
403 << "' exists that takes a left-hand operand of type '" << left
404 << "' and a right operand of type '" << right
405 << "' (or there is no acceptable conversion)";
Olli Etuaho72e35892018-06-20 11:43:08 +0300406 error(line, reasonStream.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000407}
408
Olli Etuaho856c4972016-08-08 11:38:39 +0300409void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
410 TPrecision precision,
411 TBasicType type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530412{
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400413 if (!mChecksPrecisionErrors)
Olli Etuaho383b7912016-08-05 11:22:59 +0300414 return;
Martin Radev70866b82016-07-22 15:27:42 +0300415
416 if (precision != EbpUndefined && !SupportsPrecision(type))
417 {
418 error(line, "illegal type for precision qualifier", getBasicString(type));
419 }
420
Olli Etuaho183d7e22015-11-20 15:59:09 +0200421 if (precision == EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530422 {
Olli Etuaho183d7e22015-11-20 15:59:09 +0200423 switch (type)
424 {
425 case EbtFloat:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400426 error(line, "No precision specified for (float)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300427 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200428 case EbtInt:
429 case EbtUInt:
430 UNREACHABLE(); // there's always a predeclared qualifier
Jamie Madillb98c3a82015-07-23 14:26:04 -0400431 error(line, "No precision specified (int)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300432 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200433 default:
jchen10cc2a10e2017-05-03 14:05:12 +0800434 if (IsOpaqueType(type))
Olli Etuaho183d7e22015-11-20 15:59:09 +0200435 {
jchen10cc2a10e2017-05-03 14:05:12 +0800436 error(line, "No precision specified", getBasicString(type));
Martin Radev2cc85b32016-08-05 16:22:53 +0300437 return;
438 }
Olli Etuaho183d7e22015-11-20 15:59:09 +0200439 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000440 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000441}
442
Olli Etuaho94bbed12018-03-20 14:44:53 +0200443void TParseContext::markStaticReadIfSymbol(TIntermNode *node)
444{
445 TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
446 if (swizzleNode)
447 {
448 markStaticReadIfSymbol(swizzleNode->getOperand());
449 return;
450 }
451 TIntermBinary *binaryNode = node->getAsBinaryNode();
452 if (binaryNode)
453 {
454 switch (binaryNode->getOp())
455 {
456 case EOpIndexDirect:
457 case EOpIndexIndirect:
458 case EOpIndexDirectStruct:
459 case EOpIndexDirectInterfaceBlock:
460 markStaticReadIfSymbol(binaryNode->getLeft());
461 return;
462 default:
463 return;
464 }
465 }
466 TIntermSymbol *symbolNode = node->getAsSymbolNode();
467 if (symbolNode)
468 {
469 symbolTable.markStaticRead(symbolNode->variable());
470 }
471}
472
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000473// Both test and if necessary, spit out an error, to see if the node is really
474// an l-value that can be operated on this way.
Olli Etuaho856c4972016-08-08 11:38:39 +0300475bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000476{
Olli Etuahob6fa0432016-09-28 16:28:05 +0100477 TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
Olli Etuahob6fa0432016-09-28 16:28:05 +0100478 if (swizzleNode)
479 {
480 bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
481 if (ok && swizzleNode->hasDuplicateOffsets())
482 {
483 error(line, " l-value of swizzle cannot have duplicate components", op);
484 return false;
485 }
486 return ok;
487 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000488
Olli Etuahodaf120b2018-03-20 14:21:10 +0200489 TIntermBinary *binaryNode = node->getAsBinaryNode();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530490 if (binaryNode)
491 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400492 switch (binaryNode->getOp())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530493 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400494 case EOpIndexDirect:
495 case EOpIndexIndirect:
496 case EOpIndexDirectStruct:
497 case EOpIndexDirectInterfaceBlock:
Qin Jiajia76bf01d2018-02-22 14:11:34 +0800498 if (node->getMemoryQualifier().readonly)
499 {
500 error(line, "can't modify a readonly variable", op);
501 return false;
502 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300503 return checkCanBeLValue(line, op, binaryNode->getLeft());
Jamie Madillb98c3a82015-07-23 14:26:04 -0400504 default:
505 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000506 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000507 error(line, " l-value required", op);
Olli Etuaho8a176262016-08-16 14:23:01 +0300508 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000509 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000510
jchen10cc2a10e2017-05-03 14:05:12 +0800511 std::string message;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530512 switch (node->getQualifier())
513 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400514 case EvqConst:
515 message = "can't modify a const";
516 break;
517 case EvqConstReadOnly:
518 message = "can't modify a const";
519 break;
520 case EvqAttribute:
521 message = "can't modify an attribute";
522 break;
523 case EvqFragmentIn:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400524 case EvqVertexIn:
Jiawei Shao8e4b3552017-08-30 14:20:58 +0800525 case EvqGeometryIn:
Jiawei Shaoe8ef2bc2017-08-29 13:38:57 +0800526 case EvqFlatIn:
527 case EvqSmoothIn:
528 case EvqCentroidIn:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400529 message = "can't modify an input";
530 break;
531 case EvqUniform:
532 message = "can't modify a uniform";
533 break;
534 case EvqVaryingIn:
535 message = "can't modify a varying";
536 break;
537 case EvqFragCoord:
538 message = "can't modify gl_FragCoord";
539 break;
540 case EvqFrontFacing:
541 message = "can't modify gl_FrontFacing";
542 break;
543 case EvqPointCoord:
544 message = "can't modify gl_PointCoord";
545 break;
Martin Radevb0883602016-08-04 17:48:58 +0300546 case EvqNumWorkGroups:
547 message = "can't modify gl_NumWorkGroups";
548 break;
549 case EvqWorkGroupSize:
550 message = "can't modify gl_WorkGroupSize";
551 break;
552 case EvqWorkGroupID:
553 message = "can't modify gl_WorkGroupID";
554 break;
555 case EvqLocalInvocationID:
556 message = "can't modify gl_LocalInvocationID";
557 break;
558 case EvqGlobalInvocationID:
559 message = "can't modify gl_GlobalInvocationID";
560 break;
561 case EvqLocalInvocationIndex:
562 message = "can't modify gl_LocalInvocationIndex";
563 break;
Olli Etuaho7142f6c2017-05-05 17:07:26 +0300564 case EvqViewIDOVR:
565 message = "can't modify gl_ViewID_OVR";
566 break;
Martin Radev802abe02016-08-04 17:48:32 +0300567 case EvqComputeIn:
568 message = "can't modify work group size variable";
569 break;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800570 case EvqPerVertexIn:
571 message = "can't modify any member in gl_in";
572 break;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800573 case EvqPrimitiveIDIn:
574 message = "can't modify gl_PrimitiveIDIn";
575 break;
576 case EvqInvocationID:
577 message = "can't modify gl_InvocationID";
578 break;
579 case EvqPrimitiveID:
580 if (mShaderType == GL_FRAGMENT_SHADER)
581 {
582 message = "can't modify gl_PrimitiveID in a fragment shader";
583 }
584 break;
585 case EvqLayer:
586 if (mShaderType == GL_FRAGMENT_SHADER)
587 {
588 message = "can't modify gl_Layer in a fragment shader";
589 }
590 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400591 default:
592 //
593 // Type that can't be written to?
594 //
595 if (node->getBasicType() == EbtVoid)
596 {
597 message = "can't modify void";
598 }
jchen10cc2a10e2017-05-03 14:05:12 +0800599 if (IsOpaqueType(node->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -0400600 {
jchen10cc2a10e2017-05-03 14:05:12 +0800601 message = "can't modify a variable with type ";
602 message += getBasicString(node->getBasicType());
Martin Radev2cc85b32016-08-05 16:22:53 +0300603 }
Jiajia Qinbc585152017-06-23 15:42:17 +0800604 else if (node->getMemoryQualifier().readonly)
605 {
606 message = "can't modify a readonly variable";
607 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000608 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000609
Olli Etuahodaf120b2018-03-20 14:21:10 +0200610 ASSERT(binaryNode == nullptr && swizzleNode == nullptr);
611 TIntermSymbol *symNode = node->getAsSymbolNode();
612 if (message.empty() && symNode != nullptr)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530613 {
Olli Etuaho94bbed12018-03-20 14:44:53 +0200614 symbolTable.markStaticWrite(symNode->variable());
Olli Etuaho8a176262016-08-16 14:23:01 +0300615 return true;
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000616 }
Olli Etuahodaf120b2018-03-20 14:21:10 +0200617
Jonah Ryan-Davisf563fdc2019-01-31 13:53:59 -0500618 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
Olli Etuahodaf120b2018-03-20 14:21:10 +0200619 reasonStream << "l-value required";
620 if (!message.empty())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530621 {
Olli Etuahodaf120b2018-03-20 14:21:10 +0200622 if (symNode)
623 {
624 // Symbol inside an expression can't be nameless.
625 ASSERT(symNode->variable().symbolType() != SymbolType::Empty);
626 const ImmutableString &symbol = symNode->getName();
627 reasonStream << " (" << message << " \"" << symbol << "\")";
628 }
629 else
630 {
631 reasonStream << " (" << message << ")";
632 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000633 }
Olli Etuahodaf120b2018-03-20 14:21:10 +0200634 std::string reason = reasonStream.str();
635 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000636
Olli Etuaho8a176262016-08-16 14:23:01 +0300637 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000638}
639
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000640// Both test, and if necessary spit out an error, to see if the node is really
641// a constant.
Olli Etuaho856c4972016-08-08 11:38:39 +0300642void TParseContext::checkIsConst(TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000643{
Olli Etuaho383b7912016-08-05 11:22:59 +0300644 if (node->getQualifier() != EvqConst)
645 {
646 error(node->getLine(), "constant expression required", "");
647 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000648}
649
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000650// Both test, and if necessary spit out an error, to see if the node is really
651// an integer.
Olli Etuaho856c4972016-08-08 11:38:39 +0300652void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000653{
Olli Etuaho383b7912016-08-05 11:22:59 +0300654 if (!node->isScalarInt())
655 {
656 error(node->getLine(), "integer expression required", token);
657 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000658}
659
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000660// Both test, and if necessary spit out an error, to see if we are currently
661// globally scoped.
Qiankun Miaof69682b2016-08-16 14:50:42 +0800662bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000663{
Olli Etuaho856c4972016-08-08 11:38:39 +0300664 if (!symbolTable.atGlobalLevel())
Olli Etuaho383b7912016-08-05 11:22:59 +0300665 {
666 error(line, "only allowed at global scope", token);
Qiankun Miaof69682b2016-08-16 14:50:42 +0800667 return false;
Olli Etuaho383b7912016-08-05 11:22:59 +0300668 }
Qiankun Miaof69682b2016-08-16 14:50:42 +0800669 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000670}
671
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300672// ESSL 3.00.5 sections 3.8 and 3.9.
673// If it starts "gl_" or contains two consecutive underscores, it's reserved.
674// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a webgl shader.
Olli Etuahofbb1c792018-01-19 16:26:59 +0200675bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const ImmutableString &identifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000676{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530677 static const char *reservedErrMsg = "reserved built-in name";
Olli Etuahofbb1c792018-01-19 16:26:59 +0200678 if (identifier.beginsWith("gl_"))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530679 {
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300680 error(line, reservedErrMsg, "gl_");
681 return false;
682 }
683 if (sh::IsWebGLBasedSpec(mShaderSpec))
684 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200685 if (identifier.beginsWith("webgl_"))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530686 {
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300687 error(line, reservedErrMsg, "webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300688 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000689 }
Olli Etuahofbb1c792018-01-19 16:26:59 +0200690 if (identifier.beginsWith("_webgl_"))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530691 {
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300692 error(line, reservedErrMsg, "_webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300693 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000694 }
695 }
Olli Etuahofbb1c792018-01-19 16:26:59 +0200696 if (identifier.contains("__"))
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300697 {
698 error(line,
699 "identifiers containing two consecutive underscores (__) are reserved as "
700 "possible future keywords",
Olli Etuahofbb1c792018-01-19 16:26:59 +0200701 identifier);
Olli Etuahod7cd4ae2017-07-06 15:52:49 +0300702 return false;
703 }
Olli Etuaho8a176262016-08-16 14:23:01 +0300704 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000705}
706
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300707// Make sure the argument types are correct for constructing a specific type.
Olli Etuaho856c4972016-08-08 11:38:39 +0300708bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
Olli Etuaho95ed1942018-02-01 14:01:19 +0200709 const TIntermSequence &arguments,
Olli Etuaho856c4972016-08-08 11:38:39 +0300710 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000711{
Olli Etuaho95ed1942018-02-01 14:01:19 +0200712 if (arguments.empty())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530713 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200714 error(line, "constructor does not have any arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300715 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000716 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200717
Olli Etuaho95ed1942018-02-01 14:01:19 +0200718 for (TIntermNode *arg : arguments)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530719 {
Olli Etuaho94bbed12018-03-20 14:44:53 +0200720 markStaticReadIfSymbol(arg);
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300721 const TIntermTyped *argTyped = arg->getAsTyped();
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200722 ASSERT(argTyped != nullptr);
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300723 if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType()))
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200724 {
jchen10cc2a10e2017-05-03 14:05:12 +0800725 std::string reason("cannot convert a variable with type ");
726 reason += getBasicString(argTyped->getBasicType());
727 error(line, reason.c_str(), "constructor");
Martin Radev2cc85b32016-08-05 16:22:53 +0300728 return false;
729 }
Jiajia Qinbc585152017-06-23 15:42:17 +0800730 else if (argTyped->getMemoryQualifier().writeonly)
731 {
732 error(line, "cannot convert a variable with writeonly", "constructor");
733 return false;
734 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200735 if (argTyped->getBasicType() == EbtVoid)
736 {
737 error(line, "cannot convert a void", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300738 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200739 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000740 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000741
Olli Etuaho856c4972016-08-08 11:38:39 +0300742 if (type.isArray())
743 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300744 // The size of an unsized constructor should already have been determined.
745 ASSERT(!type.isUnsizedArray());
Olli Etuaho95ed1942018-02-01 14:01:19 +0200746 if (static_cast<size_t>(type.getOutermostArraySize()) != arguments.size())
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300747 {
748 error(line, "array constructor needs one argument per array element", "constructor");
749 return false;
750 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300751 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
752 // the array.
Olli Etuaho95ed1942018-02-01 14:01:19 +0200753 for (TIntermNode *const &argNode : arguments)
Olli Etuaho856c4972016-08-08 11:38:39 +0300754 {
755 const TType &argType = argNode->getAsTyped()->getType();
Olli Etuaho7881cfd2017-08-23 18:00:21 +0300756 if (mShaderVersion < 310 && argType.isArray())
Jamie Madill34bf2d92017-02-06 13:40:59 -0500757 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300758 error(line, "constructing from a non-dereferenced array", "constructor");
Jamie Madill34bf2d92017-02-06 13:40:59 -0500759 return false;
760 }
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300761 if (!argType.isElementTypeOf(type))
Olli Etuaho856c4972016-08-08 11:38:39 +0300762 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000763 error(line, "Array constructor argument has an incorrect type", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300764 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300765 }
766 }
767 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300768 else if (type.getBasicType() == EbtStruct)
Olli Etuaho856c4972016-08-08 11:38:39 +0300769 {
770 const TFieldList &fields = type.getStruct()->fields();
Olli Etuaho95ed1942018-02-01 14:01:19 +0200771 if (fields.size() != arguments.size())
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300772 {
773 error(line,
774 "Number of constructor parameters does not match the number of structure fields",
775 "constructor");
776 return false;
777 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300778
779 for (size_t i = 0; i < fields.size(); i++)
780 {
Olli Etuaho95ed1942018-02-01 14:01:19 +0200781 if (i >= arguments.size() ||
782 arguments[i]->getAsTyped()->getType() != *fields[i]->type())
Olli Etuaho856c4972016-08-08 11:38:39 +0300783 {
784 error(line, "Structure constructor arguments do not match structure fields",
Olli Etuaho4de340a2016-12-16 09:32:03 +0000785 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300786 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300787 }
788 }
789 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300790 else
791 {
792 // We're constructing a scalar, vector, or matrix.
793
794 // Note: It's okay to have too many components available, but not okay to have unused
795 // arguments. 'full' will go to true when enough args have been seen. If we loop again,
796 // there is an extra argument, so 'overFull' will become true.
797
798 size_t size = 0;
799 bool full = false;
800 bool overFull = false;
801 bool matrixArg = false;
Olli Etuaho95ed1942018-02-01 14:01:19 +0200802 for (TIntermNode *arg : arguments)
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300803 {
804 const TIntermTyped *argTyped = arg->getAsTyped();
805 ASSERT(argTyped != nullptr);
806
Olli Etuaho487b63a2017-05-23 15:55:09 +0300807 if (argTyped->getBasicType() == EbtStruct)
808 {
809 error(line, "a struct cannot be used as a constructor argument for this type",
810 "constructor");
811 return false;
812 }
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300813 if (argTyped->getType().isArray())
814 {
815 error(line, "constructing from a non-dereferenced array", "constructor");
816 return false;
817 }
818 if (argTyped->getType().isMatrix())
819 {
820 matrixArg = true;
821 }
822
823 size += argTyped->getType().getObjectSize();
824 if (full)
825 {
826 overFull = true;
827 }
Olli Etuaho487b63a2017-05-23 15:55:09 +0300828 if (size >= type.getObjectSize())
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300829 {
830 full = true;
831 }
832 }
833
834 if (type.isMatrix() && matrixArg)
835 {
Olli Etuaho95ed1942018-02-01 14:01:19 +0200836 if (arguments.size() != 1)
Olli Etuahoa7ecec32017-05-08 17:43:55 +0300837 {
838 error(line, "constructing matrix from matrix can only take one argument",
839 "constructor");
840 return false;
841 }
842 }
843 else
844 {
845 if (size != 1 && size < type.getObjectSize())
846 {
847 error(line, "not enough data provided for construction", "constructor");
848 return false;
849 }
850 if (overFull)
851 {
852 error(line, "too many arguments", "constructor");
853 return false;
854 }
855 }
856 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300857
Olli Etuaho8a176262016-08-16 14:23:01 +0300858 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000859}
860
Jamie Madillb98c3a82015-07-23 14:26:04 -0400861// This function checks to see if a void variable has been declared and raise an error message for
862// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000863//
864// returns true in case of an error
865//
Olli Etuaho856c4972016-08-08 11:38:39 +0300866bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200867 const ImmutableString &identifier,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400868 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000869{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300870 if (type == EbtVoid)
871 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200872 error(line, "illegal use of type 'void'", identifier);
Olli Etuaho8a176262016-08-16 14:23:01 +0300873 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300874 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000875
Olli Etuaho8a176262016-08-16 14:23:01 +0300876 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000877}
878
Jamie Madillb98c3a82015-07-23 14:26:04 -0400879// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300880// or not.
Olli Etuaho56229f12017-07-10 14:16:33 +0300881bool TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000882{
Olli Etuaho37d96cc2017-07-11 14:14:03 +0300883 if (type->getBasicType() != EbtBool || !type->isScalar())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530884 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000885 error(line, "boolean expression expected", "");
Olli Etuaho56229f12017-07-10 14:16:33 +0300886 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530887 }
Olli Etuaho56229f12017-07-10 14:16:33 +0300888 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000889}
890
Jamie Madillb98c3a82015-07-23 14:26:04 -0400891// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300892// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300893void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000894{
Martin Radev4a9cd802016-09-01 16:51:51 +0300895 if (pType.getBasicType() != EbtBool || pType.isAggregate())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530896 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000897 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530898 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000899}
900
jchen10cc2a10e2017-05-03 14:05:12 +0800901bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
902 const TTypeSpecifierNonArray &pType,
903 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000904{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530905 if (pType.type == EbtStruct)
906 {
Olli Etuaho0f684632017-07-13 12:42:15 +0300907 if (ContainsSampler(pType.userDef))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530908 {
Jonah Ryan-Davisf563fdc2019-01-31 13:53:59 -0500909 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
Olli Etuaho4de340a2016-12-16 09:32:03 +0000910 reasonStream << reason << " (structure contains a sampler)";
911 std::string reasonStr = reasonStream.str();
912 error(line, reasonStr.c_str(), getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300913 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000914 }
jchen10cc2a10e2017-05-03 14:05:12 +0800915 // only samplers need to be checked from structs, since other opaque types can't be struct
916 // members.
Olli Etuaho8a176262016-08-16 14:23:01 +0300917 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530918 }
jchen10cc2a10e2017-05-03 14:05:12 +0800919 else if (IsOpaqueType(pType.type))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530920 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000921 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300922 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000923 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000924
Olli Etuaho8a176262016-08-16 14:23:01 +0300925 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000926}
927
Olli Etuaho856c4972016-08-08 11:38:39 +0300928void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
929 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400930{
931 if (pType.layoutQualifier.location != -1)
932 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400933 error(line, "location must only be specified for a single input or output variable",
934 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400935 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400936}
937
Olli Etuaho856c4972016-08-08 11:38:39 +0300938void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
939 const TLayoutQualifier &layoutQualifier)
940{
941 if (layoutQualifier.location != -1)
942 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000943 const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs";
944 if (mShaderVersion >= 310)
945 {
946 errorMsg =
Jiawei Shao4cc89e22017-08-31 14:25:54 +0800947 "invalid layout qualifier: only valid on shader inputs, outputs, and uniforms";
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000948 }
949 error(location, errorMsg, "location");
Olli Etuaho856c4972016-08-08 11:38:39 +0300950 }
951}
952
Qin Jiajiaca68d982017-09-18 16:41:56 +0800953void TParseContext::checkStd430IsForShaderStorageBlock(const TSourceLoc &location,
954 const TLayoutBlockStorage &blockStorage,
955 const TQualifier &qualifier)
956{
957 if (blockStorage == EbsStd430 && qualifier != EvqBuffer)
958 {
959 error(location, "The std430 layout is supported only for shader storage blocks.", "std430");
960 }
961}
962
Martin Radev2cc85b32016-08-05 16:22:53 +0300963void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
964 TQualifier qualifier,
965 const TType &type)
966{
Martin Radev2cc85b32016-08-05 16:22:53 +0300967 ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
jchen10cc2a10e2017-05-03 14:05:12 +0800968 if (IsOpaqueType(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530969 {
jchen10cc2a10e2017-05-03 14:05:12 +0800970 error(line, "opaque types cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000971 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000972}
973
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000974// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300975unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000976{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530977 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000978
Olli Etuaho1dfd8ae2018-10-01 15:59:59 +0300979 // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be
980 // safe against corner cases we still check for constant folding. Some interpretations of the
981 // spec have allowed constant expressions with side effects - like array length() method on a
982 // non-constant array.
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200983 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000984 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000985 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300986 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000987 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000988
Olli Etuaho856c4972016-08-08 11:38:39 +0300989 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400990
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000991 if (constant->getBasicType() == EbtUInt)
992 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300993 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000994 }
995 else
996 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300997 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000998
Olli Etuaho856c4972016-08-08 11:38:39 +0300999 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001000 {
Nicolas Capens906744a2014-06-06 15:18:07 -04001001 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +03001002 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001003 }
Nicolas Capens906744a2014-06-06 15:18:07 -04001004
Olli Etuaho856c4972016-08-08 11:38:39 +03001005 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -04001006 }
1007
Olli Etuaho856c4972016-08-08 11:38:39 +03001008 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -04001009 {
1010 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +03001011 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -04001012 }
1013
1014 // The size of arrays is restricted here to prevent issues further down the
1015 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
1016 // 4096 registers so this should be reasonable even for aggressively optimizable code.
1017 const unsigned int sizeLimit = 65536;
1018
Olli Etuaho856c4972016-08-08 11:38:39 +03001019 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -04001020 {
1021 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +03001022 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001023 }
Olli Etuaho856c4972016-08-08 11:38:39 +03001024
1025 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001026}
1027
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001028// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +03001029bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
1030 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001031{
Olli Etuaho8a176262016-08-16 14:23:01 +03001032 if ((elementQualifier.qualifier == EvqAttribute) ||
1033 (elementQualifier.qualifier == EvqVertexIn) ||
1034 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +03001035 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001036 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +03001037 TType(elementQualifier).getQualifierString());
1038 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001039 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001040
Olli Etuaho8a176262016-08-16 14:23:01 +03001041 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001042}
1043
Olli Etuaho8a176262016-08-16 14:23:01 +03001044// See if this element type can be formed into an array.
Olli Etuahoe0803872017-08-23 15:30:23 +03001045bool TParseContext::checkArrayElementIsNotArray(const TSourceLoc &line,
1046 const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001047{
Olli Etuaho7881cfd2017-08-23 18:00:21 +03001048 if (mShaderVersion < 310 && elementType.isArray())
Jamie Madill06145232015-05-13 13:10:01 -04001049 {
Olli Etuaho72e35892018-06-20 11:43:08 +03001050 TInfoSinkBase typeString;
1051 typeString << TType(elementType);
1052 error(line, "cannot declare arrays of arrays", typeString.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001053 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001054 }
Olli Etuahoe0803872017-08-23 15:30:23 +03001055 return true;
1056}
1057
1058// Check if this qualified element type can be formed into an array. This is only called when array
1059// brackets are associated with an identifier in a declaration, like this:
1060// float a[2];
1061// Similar checks are done in addFullySpecifiedType for array declarations where the array brackets
1062// are associated with the type, like this:
1063// float[2] a;
1064bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
1065 const TPublicType &elementType)
1066{
1067 if (!checkArrayElementIsNotArray(indexLocation, elementType))
1068 {
1069 return false;
1070 }
Olli Etuahocc36b982015-07-10 14:14:18 +03001071 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
1072 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
1073 // 4.3.4).
Jiawei Shao492b5f52017-12-13 09:39:27 +08001074 // Geometry shader requires each user-defined input be declared as arrays or inside input
1075 // blocks declared as arrays (GL_EXT_geometry_shader section 11.1gs.4.3). For the purposes of
1076 // interface matching, such variables and blocks are treated as though they were not declared
1077 // as arrays (GL_EXT_geometry_shader section 7.4.1).
Martin Radev4a9cd802016-09-01 16:51:51 +03001078 if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
Jiawei Shao492b5f52017-12-13 09:39:27 +08001079 sh::IsVarying(elementType.qualifier) &&
1080 !IsGeometryShaderInput(mShaderType, elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +03001081 {
Olli Etuaho72e35892018-06-20 11:43:08 +03001082 TInfoSinkBase typeString;
1083 typeString << TType(elementType);
Olli Etuahoe0803872017-08-23 15:30:23 +03001084 error(indexLocation, "cannot declare arrays of structs of this qualifier",
Olli Etuaho72e35892018-06-20 11:43:08 +03001085 typeString.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001086 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +03001087 }
Olli Etuahoe0803872017-08-23 15:30:23 +03001088 return checkIsValidQualifierForArray(indexLocation, elementType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001089}
1090
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001091// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +03001092void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
Olli Etuahofbb1c792018-01-19 16:26:59 +02001093 const ImmutableString &identifier,
Olli Etuaho55bde912017-10-25 13:41:13 +03001094 TType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001095{
Olli Etuaho3739d232015-04-08 12:23:44 +03001096 ASSERT(type != nullptr);
Olli Etuaho55bde912017-10-25 13:41:13 +03001097 if (type->getQualifier() == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +00001098 {
1099 // Make the qualifier make sense.
Olli Etuaho55bde912017-10-25 13:41:13 +03001100 type->setQualifier(EvqTemporary);
Olli Etuaho3739d232015-04-08 12:23:44 +03001101
1102 // Generate informative error messages for ESSL1.
1103 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001104 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +00001105 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05301106 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001107 "structures containing arrays may not be declared constant since they cannot be "
1108 "initialized",
Olli Etuahofbb1c792018-01-19 16:26:59 +02001109 identifier);
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +00001110 }
1111 else
1112 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02001113 error(line, "variables with qualifier 'const' must be initialized", identifier);
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +00001114 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001115 }
Olli Etuaho55bde912017-10-25 13:41:13 +03001116 // This will make the type sized if it isn't sized yet.
Olli Etuahofbb1c792018-01-19 16:26:59 +02001117 checkIsNotUnsizedArray(line, "implicitly sized arrays need to be initialized", identifier,
1118 type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001119}
1120
Olli Etuaho2935c582015-04-08 14:32:06 +03001121// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001122// and update the symbol table.
1123//
Olli Etuaho2935c582015-04-08 14:32:06 +03001124// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001125//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001126bool TParseContext::declareVariable(const TSourceLoc &line,
Olli Etuahofbb1c792018-01-19 16:26:59 +02001127 const ImmutableString &identifier,
Olli Etuahob60d30f2018-01-16 12:31:06 +02001128 const TType *type,
Olli Etuaho2935c582015-04-08 14:32:06 +03001129 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001130{
Olli Etuaho2935c582015-04-08 14:32:06 +03001131 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001132
Olli Etuahofbb1c792018-01-19 16:26:59 +02001133 (*variable) = new TVariable(&symbolTable, identifier, type, SymbolType::UserDefined);
Olli Etuaho195be942017-12-04 23:40:14 +02001134
Olli Etuahoa78092c2018-09-26 14:16:13 +03001135 ASSERT(type->getLayoutQualifier().index == -1 ||
1136 (isExtensionEnabled(TExtension::EXT_blend_func_extended) &&
1137 mShaderType == GL_FRAGMENT_SHADER && mShaderVersion >= 300));
1138 if (type->getQualifier() == EvqFragmentOut)
1139 {
1140 if (type->getLayoutQualifier().index != -1 && type->getLayoutQualifier().location == -1)
1141 {
1142 error(line,
1143 "If index layout qualifier is specified for a fragment output, location must "
1144 "also be specified.",
1145 "index");
1146 return false;
1147 }
1148 }
1149 else
1150 {
1151 checkIndexIsNotSpecified(line, type->getLayoutQualifier().index);
1152 }
1153
Olli Etuahob60d30f2018-01-16 12:31:06 +02001154 checkBindingIsValid(line, *type);
Olli Etuaho43364892017-02-13 16:00:12 +00001155
Olli Etuaho856c4972016-08-08 11:38:39 +03001156 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001157
Olli Etuaho2935c582015-04-08 14:32:06 +03001158 // gl_LastFragData may be redeclared with a new precision qualifier
Olli Etuahofbb1c792018-01-19 16:26:59 +02001159 if (type->isArray() && identifier.beginsWith("gl_LastFragData"))
Olli Etuaho2935c582015-04-08 14:32:06 +03001160 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001161 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
Olli Etuahofbb1c792018-01-19 16:26:59 +02001162 symbolTable.findBuiltIn(ImmutableString("gl_MaxDrawBuffers"), mShaderVersion));
Olli Etuahob60d30f2018-01-16 12:31:06 +02001163 if (type->isArrayOfArrays())
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001164 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02001165 error(line, "redeclaration of gl_LastFragData as an array of arrays", identifier);
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001166 return false;
1167 }
Olli Etuahob60d30f2018-01-16 12:31:06 +02001168 else if (static_cast<int>(type->getOutermostArraySize()) ==
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001169 maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +03001170 {
Olli Etuahodd21ecf2018-01-10 12:42:09 +02001171 if (const TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +03001172 {
Olli Etuaho54a29ff2017-11-28 17:35:20 +02001173 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->extension());
Olli Etuaho2935c582015-04-08 14:32:06 +03001174 }
1175 }
1176 else
1177 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001178 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
Olli Etuahofbb1c792018-01-19 16:26:59 +02001179 identifier);
Olli Etuaho2935c582015-04-08 14:32:06 +03001180 return false;
1181 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001182 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001183
Olli Etuaho8a176262016-08-16 14:23:01 +03001184 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +03001185 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001186
Olli Etuaho437664b2018-02-28 15:38:14 +02001187 if (!symbolTable.declare(*variable))
Olli Etuaho2935c582015-04-08 14:32:06 +03001188 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02001189 error(line, "redefinition", identifier);
Olli Etuaho2935c582015-04-08 14:32:06 +03001190 return false;
1191 }
1192
Olli Etuahob60d30f2018-01-16 12:31:06 +02001193 if (!checkIsNonVoid(line, identifier, type->getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +03001194 return false;
1195
1196 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001197}
1198
Martin Radev70866b82016-07-22 15:27:42 +03001199void TParseContext::checkIsParameterQualifierValid(
1200 const TSourceLoc &line,
1201 const TTypeQualifierBuilder &typeQualifierBuilder,
1202 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301203{
Olli Etuahocce89652017-06-19 16:04:09 +03001204 // The only parameter qualifiers a parameter can have are in, out, inout or const.
Olli Etuaho77ba4082016-12-16 12:01:18 +00001205 TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03001206
1207 if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301208 {
Martin Radev2cc85b32016-08-05 16:22:53 +03001209 checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type);
1210 }
1211
1212 if (!IsImage(type->getBasicType()))
1213 {
Olli Etuaho43364892017-02-13 16:00:12 +00001214 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line);
Martin Radev2cc85b32016-08-05 16:22:53 +03001215 }
1216 else
1217 {
1218 type->setMemoryQualifier(typeQualifier.memoryQualifier);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001219 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001220
Martin Radev70866b82016-07-22 15:27:42 +03001221 type->setQualifier(typeQualifier.qualifier);
1222
1223 if (typeQualifier.precision != EbpUndefined)
1224 {
1225 type->setPrecision(typeQualifier.precision);
1226 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001227}
1228
Olli Etuaho703671e2017-11-08 17:47:18 +02001229template <size_t size>
1230bool TParseContext::checkCanUseOneOfExtensions(const TSourceLoc &line,
1231 const std::array<TExtension, size> &extensions)
1232{
1233 ASSERT(!extensions.empty());
1234 const TExtensionBehavior &extBehavior = extensionBehavior();
1235
1236 bool canUseWithWarning = false;
1237 bool canUseWithoutWarning = false;
1238
1239 const char *errorMsgString = "";
1240 TExtension errorMsgExtension = TExtension::UNDEFINED;
1241
1242 for (TExtension extension : extensions)
1243 {
1244 auto extIter = extBehavior.find(extension);
1245 if (canUseWithWarning)
1246 {
1247 // We already have an extension that we can use, but with a warning.
1248 // See if we can use the alternative extension without a warning.
1249 if (extIter == extBehavior.end())
1250 {
1251 continue;
1252 }
1253 if (extIter->second == EBhEnable || extIter->second == EBhRequire)
1254 {
1255 canUseWithoutWarning = true;
1256 break;
1257 }
1258 continue;
1259 }
1260 if (extIter == extBehavior.end())
1261 {
1262 errorMsgString = "extension is not supported";
1263 errorMsgExtension = extension;
1264 }
1265 else if (extIter->second == EBhUndefined || extIter->second == EBhDisable)
1266 {
1267 errorMsgString = "extension is disabled";
1268 errorMsgExtension = extension;
1269 }
1270 else if (extIter->second == EBhWarn)
1271 {
1272 errorMsgExtension = extension;
1273 canUseWithWarning = true;
1274 }
1275 else
1276 {
1277 ASSERT(extIter->second == EBhEnable || extIter->second == EBhRequire);
1278 canUseWithoutWarning = true;
1279 break;
1280 }
1281 }
1282
1283 if (canUseWithoutWarning)
1284 {
1285 return true;
1286 }
1287 if (canUseWithWarning)
1288 {
1289 warning(line, "extension is being used", GetExtensionNameString(errorMsgExtension));
1290 return true;
1291 }
1292 error(line, errorMsgString, GetExtensionNameString(errorMsgExtension));
1293 return false;
1294}
1295
1296template bool TParseContext::checkCanUseOneOfExtensions(
1297 const TSourceLoc &line,
1298 const std::array<TExtension, 1> &extensions);
1299template bool TParseContext::checkCanUseOneOfExtensions(
1300 const TSourceLoc &line,
1301 const std::array<TExtension, 2> &extensions);
1302template bool TParseContext::checkCanUseOneOfExtensions(
1303 const TSourceLoc &line,
1304 const std::array<TExtension, 3> &extensions);
1305
Olli Etuaho2a1e8f92017-07-14 11:49:36 +03001306bool TParseContext::checkCanUseExtension(const TSourceLoc &line, TExtension extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001307{
Olli Etuaho2a1e8f92017-07-14 11:49:36 +03001308 ASSERT(extension != TExtension::UNDEFINED);
Corentin Wallez1d33c212017-11-13 10:21:39 -08001309 return checkCanUseOneOfExtensions(line, std::array<TExtension, 1u>{{extension}});
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001310}
1311
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001312// ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause
1313// compile-time or link-time errors are the same whether or not the declaration is empty".
1314// This function implements all the checks that are done on qualifiers regardless of if the
1315// declaration is empty.
1316void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier,
1317 const sh::TLayoutQualifier &layoutQualifier,
1318 const TSourceLoc &location)
1319{
1320 if (qualifier == EvqShared && !layoutQualifier.isEmpty())
1321 {
1322 error(location, "Shared memory declarations cannot have layout specified", "layout");
1323 }
1324
1325 if (layoutQualifier.matrixPacking != EmpUnspecified)
1326 {
1327 error(location, "layout qualifier only valid for interface blocks",
1328 getMatrixPackingString(layoutQualifier.matrixPacking));
1329 return;
1330 }
1331
1332 if (layoutQualifier.blockStorage != EbsUnspecified)
1333 {
1334 error(location, "layout qualifier only valid for interface blocks",
1335 getBlockStorageString(layoutQualifier.blockStorage));
1336 return;
1337 }
1338
1339 if (qualifier == EvqFragmentOut)
1340 {
1341 if (layoutQualifier.location != -1 && layoutQualifier.yuv == true)
1342 {
1343 error(location, "invalid layout qualifier combination", "yuv");
1344 return;
1345 }
1346 }
1347 else
1348 {
1349 checkYuvIsNotSpecified(location, layoutQualifier.yuv);
1350 }
1351
Olli Etuaho95468d12017-05-04 11:14:34 +03001352 // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous
1353 // parsing steps. So it needs to be checked here.
Mingyu Huebab6702019-04-19 14:36:45 -07001354 if (anyMultiviewExtensionAvailable() && mShaderVersion < 300 && qualifier == EvqVertexIn)
Olli Etuaho95468d12017-05-04 11:14:34 +03001355 {
1356 error(location, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
1357 }
1358
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001359 bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut;
Jiawei Shao4cc89e22017-08-31 14:25:54 +08001360 if (mShaderVersion >= 310)
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001361 {
Jiawei Shao4cc89e22017-08-31 14:25:54 +08001362 canHaveLocation = canHaveLocation || qualifier == EvqUniform || IsVarying(qualifier);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001363 // We're not checking whether the uniform location is in range here since that depends on
1364 // the type of the variable.
1365 // The type can only be fully determined for non-empty declarations.
1366 }
1367 if (!canHaveLocation)
1368 {
1369 checkLocationIsNotSpecified(location, layoutQualifier);
1370 }
1371}
1372
jchen104cdac9e2017-05-08 11:01:20 +08001373void TParseContext::atomicCounterQualifierErrorCheck(const TPublicType &publicType,
1374 const TSourceLoc &location)
1375{
1376 if (publicType.precision != EbpHigh)
1377 {
1378 error(location, "Can only be highp", "atomic counter");
1379 }
1380 // dEQP enforces compile error if location is specified. See uniform_location.test.
1381 if (publicType.layoutQualifier.location != -1)
1382 {
1383 error(location, "location must not be set for atomic_uint", "layout");
1384 }
1385 if (publicType.layoutQualifier.binding == -1)
1386 {
1387 error(location, "no binding specified", "atomic counter");
1388 }
1389}
1390
Olli Etuaho55bde912017-10-25 13:41:13 +03001391void TParseContext::emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location)
Martin Radevb8b01222016-11-20 23:25:53 +02001392{
Olli Etuaho55bde912017-10-25 13:41:13 +03001393 if (type.isUnsizedArray())
Martin Radevb8b01222016-11-20 23:25:53 +02001394 {
1395 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1396 // error. It is assumed that this applies to empty declarations as well.
1397 error(location, "empty array declaration needs to specify a size", "");
1398 }
Olli Etuahoa78092c2018-09-26 14:16:13 +03001399
1400 if (type.getQualifier() != EvqFragmentOut)
1401 {
1402 checkIndexIsNotSpecified(location, type.getLayoutQualifier().index);
1403 }
Martin Radevb8b01222016-11-20 23:25:53 +02001404}
1405
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001406// These checks are done for all declarations that are non-empty. They're done for non-empty
1407// declarations starting a declarator list, and declarators that follow an empty declaration.
1408void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
1409 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -04001410{
Olli Etuahofa33d582015-04-09 14:33:12 +03001411 switch (publicType.qualifier)
1412 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001413 case EvqVaryingIn:
1414 case EvqVaryingOut:
1415 case EvqAttribute:
1416 case EvqVertexIn:
1417 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +03001418 case EvqComputeIn:
Martin Radev4a9cd802016-09-01 16:51:51 +03001419 if (publicType.getBasicType() == EbtStruct)
Jamie Madillb98c3a82015-07-23 14:26:04 -04001420 {
1421 error(identifierLocation, "cannot be used with a structure",
1422 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +03001423 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001424 }
Jiajia Qinbc585152017-06-23 15:42:17 +08001425 break;
1426 case EvqBuffer:
1427 if (publicType.getBasicType() != EbtInterfaceBlock)
1428 {
1429 error(identifierLocation,
1430 "cannot declare buffer variables at global scope(outside a block)",
1431 getQualifierString(publicType.qualifier));
1432 return;
1433 }
1434 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001435 default:
1436 break;
Olli Etuahofa33d582015-04-09 14:33:12 +03001437 }
jchen10cc2a10e2017-05-03 14:05:12 +08001438 std::string reason(getBasicString(publicType.getBasicType()));
1439 reason += "s must be uniform";
Jamie Madillb98c3a82015-07-23 14:26:04 -04001440 if (publicType.qualifier != EvqUniform &&
jchen10cc2a10e2017-05-03 14:05:12 +08001441 !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str()))
Martin Radev2cc85b32016-08-05 16:22:53 +03001442 {
1443 return;
1444 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001445
Andrei Volykhina5527072017-03-22 16:46:30 +03001446 if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal &&
1447 publicType.qualifier != EvqConst) &&
1448 publicType.getBasicType() == EbtYuvCscStandardEXT)
1449 {
1450 error(identifierLocation, "cannot be used with a yuvCscStandardEXT",
1451 getQualifierString(publicType.qualifier));
1452 return;
1453 }
1454
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001455 if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform)
1456 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001457 // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized.
1458 // But invalid shaders may still reach here with an unsized array declaration.
Olli Etuaho55bde912017-10-25 13:41:13 +03001459 TType type(publicType);
1460 if (!type.isUnsizedArray())
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001461 {
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001462 checkUniformLocationInRange(identifierLocation, type.getLocationCount(),
1463 publicType.layoutQualifier);
1464 }
1465 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001466
Olli Etuahobb7e5a72017-04-24 10:16:44 +03001467 // check for layout qualifier issues
1468 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
Andrei Volykhina5527072017-03-22 16:46:30 +03001469
Martin Radev2cc85b32016-08-05 16:22:53 +03001470 if (IsImage(publicType.getBasicType()))
1471 {
1472
1473 switch (layoutQualifier.imageInternalFormat)
1474 {
1475 case EiifRGBA32F:
1476 case EiifRGBA16F:
1477 case EiifR32F:
1478 case EiifRGBA8:
1479 case EiifRGBA8_SNORM:
1480 if (!IsFloatImage(publicType.getBasicType()))
1481 {
1482 error(identifierLocation,
1483 "internal image format requires a floating image type",
1484 getBasicString(publicType.getBasicType()));
1485 return;
1486 }
1487 break;
1488 case EiifRGBA32I:
1489 case EiifRGBA16I:
1490 case EiifRGBA8I:
1491 case EiifR32I:
1492 if (!IsIntegerImage(publicType.getBasicType()))
1493 {
1494 error(identifierLocation,
1495 "internal image format requires an integer image type",
1496 getBasicString(publicType.getBasicType()));
1497 return;
1498 }
1499 break;
1500 case EiifRGBA32UI:
1501 case EiifRGBA16UI:
1502 case EiifRGBA8UI:
1503 case EiifR32UI:
1504 if (!IsUnsignedImage(publicType.getBasicType()))
1505 {
1506 error(identifierLocation,
1507 "internal image format requires an unsigned image type",
1508 getBasicString(publicType.getBasicType()));
1509 return;
1510 }
1511 break;
1512 case EiifUnspecified:
1513 error(identifierLocation, "layout qualifier", "No image internal format specified");
1514 return;
1515 default:
1516 error(identifierLocation, "layout qualifier", "unrecognized token");
1517 return;
1518 }
1519
1520 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
1521 switch (layoutQualifier.imageInternalFormat)
1522 {
1523 case EiifR32F:
1524 case EiifR32I:
1525 case EiifR32UI:
1526 break;
1527 default:
1528 if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
1529 {
1530 error(identifierLocation, "layout qualifier",
1531 "Except for images with the r32f, r32i and r32ui format qualifiers, "
1532 "image variables must be qualified readonly and/or writeonly");
1533 return;
1534 }
1535 break;
1536 }
1537 }
1538 else
1539 {
Olli Etuaho43364892017-02-13 16:00:12 +00001540 checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat);
Olli Etuaho43364892017-02-13 16:00:12 +00001541 checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
1542 }
jchen104cdac9e2017-05-08 11:01:20 +08001543
1544 if (IsAtomicCounter(publicType.getBasicType()))
1545 {
1546 atomicCounterQualifierErrorCheck(publicType, identifierLocation);
1547 }
1548 else
1549 {
1550 checkOffsetIsNotSpecified(identifierLocation, layoutQualifier.offset);
1551 }
Olli Etuaho43364892017-02-13 16:00:12 +00001552}
Martin Radev2cc85b32016-08-05 16:22:53 +03001553
Olli Etuaho43364892017-02-13 16:00:12 +00001554void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type)
1555{
1556 TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001557 // Note that the ESSL 3.10 section 4.4.5 is not particularly clear on how the binding qualifier
1558 // on arrays of arrays should be handled. We interpret the spec so that the binding value is
1559 // incremented for each element of the innermost nested arrays. This is in line with how arrays
1560 // of arrays of blocks are specified to behave in GLSL 4.50 and a conservative interpretation
1561 // when it comes to which shaders are accepted by the compiler.
1562 int arrayTotalElementCount = type.getArraySizeProduct();
Olli Etuaho43364892017-02-13 16:00:12 +00001563 if (IsImage(type.getBasicType()))
1564 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001565 checkImageBindingIsValid(identifierLocation, layoutQualifier.binding,
1566 arrayTotalElementCount);
Olli Etuaho43364892017-02-13 16:00:12 +00001567 }
1568 else if (IsSampler(type.getBasicType()))
1569 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001570 checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding,
1571 arrayTotalElementCount);
Olli Etuaho43364892017-02-13 16:00:12 +00001572 }
jchen104cdac9e2017-05-08 11:01:20 +08001573 else if (IsAtomicCounter(type.getBasicType()))
1574 {
1575 checkAtomicCounterBindingIsValid(identifierLocation, layoutQualifier.binding);
1576 }
Olli Etuaho43364892017-02-13 16:00:12 +00001577 else
1578 {
1579 ASSERT(!IsOpaqueType(type.getBasicType()));
1580 checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
Martin Radev2cc85b32016-08-05 16:22:53 +03001581 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001582}
1583
Olli Etuaho856c4972016-08-08 11:38:39 +03001584void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
Olli Etuahofbb1c792018-01-19 16:26:59 +02001585 const ImmutableString &layoutQualifierName,
Olli Etuaho856c4972016-08-08 11:38:39 +03001586 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001587{
1588
1589 if (mShaderVersion < versionRequired)
1590 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02001591 error(location, "invalid layout qualifier: not supported", layoutQualifierName);
Martin Radev802abe02016-08-04 17:48:32 +03001592 }
1593}
1594
Olli Etuaho856c4972016-08-08 11:38:39 +03001595bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1596 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001597{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001598 const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
Martin Radev802abe02016-08-04 17:48:32 +03001599 for (size_t i = 0u; i < localSize.size(); ++i)
1600 {
1601 if (localSize[i] != -1)
1602 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001603 error(location,
1604 "invalid layout qualifier: only valid when used with 'in' in a compute shader "
1605 "global layout declaration",
1606 getWorkGroupSizeString(i));
Olli Etuaho8a176262016-08-16 14:23:01 +03001607 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001608 }
1609 }
1610
Olli Etuaho8a176262016-08-16 14:23:01 +03001611 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001612}
1613
Olli Etuaho43364892017-02-13 16:00:12 +00001614void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
Martin Radev2cc85b32016-08-05 16:22:53 +03001615 TLayoutImageInternalFormat internalFormat)
1616{
1617 if (internalFormat != EiifUnspecified)
1618 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001619 error(location, "invalid layout qualifier: only valid when used with images",
1620 getImageInternalFormatString(internalFormat));
Martin Radev2cc85b32016-08-05 16:22:53 +03001621 }
Olli Etuaho43364892017-02-13 16:00:12 +00001622}
1623
Olli Etuahoa78092c2018-09-26 14:16:13 +03001624void TParseContext::checkIndexIsNotSpecified(const TSourceLoc &location, int index)
1625{
1626 if (index != -1)
1627 {
1628 error(location,
1629 "invalid layout qualifier: only valid when used with a fragment shader output in "
1630 "ESSL version >= 3.00 and EXT_blend_func_extended is enabled",
1631 "index");
1632 }
1633}
1634
Olli Etuaho43364892017-02-13 16:00:12 +00001635void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
1636{
1637 if (binding != -1)
1638 {
1639 error(location,
1640 "invalid layout qualifier: only valid when used with opaque types or blocks",
1641 "binding");
1642 }
1643}
1644
jchen104cdac9e2017-05-08 11:01:20 +08001645void TParseContext::checkOffsetIsNotSpecified(const TSourceLoc &location, int offset)
1646{
1647 if (offset != -1)
1648 {
1649 error(location, "invalid layout qualifier: only valid when used with atomic counters",
1650 "offset");
1651 }
1652}
1653
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001654void TParseContext::checkImageBindingIsValid(const TSourceLoc &location,
1655 int binding,
1656 int arrayTotalElementCount)
Olli Etuaho43364892017-02-13 16:00:12 +00001657{
1658 // Expects arraySize to be 1 when setting binding for only a single variable.
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001659 if (binding >= 0 && binding + arrayTotalElementCount > mMaxImageUnits)
Olli Etuaho43364892017-02-13 16:00:12 +00001660 {
1661 error(location, "image binding greater than gl_MaxImageUnits", "binding");
1662 }
1663}
1664
1665void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location,
1666 int binding,
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001667 int arrayTotalElementCount)
Olli Etuaho43364892017-02-13 16:00:12 +00001668{
1669 // Expects arraySize to be 1 when setting binding for only a single variable.
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001670 if (binding >= 0 && binding + arrayTotalElementCount > mMaxCombinedTextureImageUnits)
Olli Etuaho43364892017-02-13 16:00:12 +00001671 {
1672 error(location, "sampler binding greater than maximum texture units", "binding");
1673 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001674}
1675
Jiajia Qinbc585152017-06-23 15:42:17 +08001676void TParseContext::checkBlockBindingIsValid(const TSourceLoc &location,
1677 const TQualifier &qualifier,
1678 int binding,
1679 int arraySize)
jchen10af713a22017-04-19 09:10:56 +08001680{
1681 int size = (arraySize == 0 ? 1 : arraySize);
Jiajia Qinbc585152017-06-23 15:42:17 +08001682 if (qualifier == EvqUniform)
jchen10af713a22017-04-19 09:10:56 +08001683 {
Jiajia Qinbc585152017-06-23 15:42:17 +08001684 if (binding + size > mMaxUniformBufferBindings)
1685 {
1686 error(location, "uniform block binding greater than MAX_UNIFORM_BUFFER_BINDINGS",
1687 "binding");
1688 }
1689 }
1690 else if (qualifier == EvqBuffer)
1691 {
1692 if (binding + size > mMaxShaderStorageBufferBindings)
1693 {
1694 error(location,
1695 "shader storage block binding greater than MAX_SHADER_STORAGE_BUFFER_BINDINGS",
1696 "binding");
1697 }
jchen10af713a22017-04-19 09:10:56 +08001698 }
1699}
jchen104cdac9e2017-05-08 11:01:20 +08001700void TParseContext::checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding)
1701{
1702 if (binding >= mMaxAtomicCounterBindings)
1703 {
1704 error(location, "atomic counter binding greater than gl_MaxAtomicCounterBindings",
1705 "binding");
1706 }
1707}
jchen10af713a22017-04-19 09:10:56 +08001708
Olli Etuaho6ca2b652017-02-19 18:05:10 +00001709void TParseContext::checkUniformLocationInRange(const TSourceLoc &location,
1710 int objectLocationCount,
1711 const TLayoutQualifier &layoutQualifier)
1712{
1713 int loc = layoutQualifier.location;
1714 if (loc >= 0 && loc + objectLocationCount > mMaxUniformLocations)
1715 {
1716 error(location, "Uniform location out of range", "location");
1717 }
1718}
1719
Andrei Volykhina5527072017-03-22 16:46:30 +03001720void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv)
1721{
1722 if (yuv != false)
1723 {
1724 error(location, "invalid layout qualifier: only valid on program outputs", "yuv");
1725 }
1726}
1727
Jiajia Qinbc585152017-06-23 15:42:17 +08001728void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandidate,
1729 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001730{
1731 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1732 {
Olli Etuahod4bd9632018-03-08 16:32:44 +02001733 TQualifier qual = fnCandidate->getParam(i)->getType().getQualifier();
Jiajia Qinbc585152017-06-23 15:42:17 +08001734 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho94bbed12018-03-20 14:44:53 +02001735 bool argumentIsRead = (IsQualifierUnspecified(qual) || qual == EvqIn || qual == EvqInOut ||
1736 qual == EvqConstReadOnly);
1737 if (argumentIsRead)
Jiajia Qinbc585152017-06-23 15:42:17 +08001738 {
Olli Etuaho94bbed12018-03-20 14:44:53 +02001739 markStaticReadIfSymbol(argument);
1740 if (!IsImage(argument->getBasicType()))
Jiajia Qinbc585152017-06-23 15:42:17 +08001741 {
Olli Etuaho94bbed12018-03-20 14:44:53 +02001742 if (argument->getMemoryQualifier().writeonly)
1743 {
1744 error(argument->getLine(),
1745 "Writeonly value cannot be passed for 'in' or 'inout' parameters.",
1746 fnCall->functionName());
1747 return;
1748 }
Jiajia Qinbc585152017-06-23 15:42:17 +08001749 }
1750 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001751 if (qual == EvqOut || qual == EvqInOut)
1752 {
Olli Etuaho8a176262016-08-16 14:23:01 +03001753 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001754 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001755 error(argument->getLine(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00001756 "Constant value cannot be passed for 'out' or 'inout' parameters.",
Olli Etuaho0c371002017-12-13 17:00:25 +04001757 fnCall->functionName());
Olli Etuaho383b7912016-08-05 11:22:59 +03001758 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001759 }
1760 }
1761 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001762}
1763
Martin Radev70866b82016-07-22 15:27:42 +03001764void TParseContext::checkInvariantVariableQualifier(bool invariant,
1765 const TQualifier qualifier,
1766 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001767{
Martin Radev70866b82016-07-22 15:27:42 +03001768 if (!invariant)
1769 return;
1770
1771 if (mShaderVersion < 300)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001772 {
Martin Radev70866b82016-07-22 15:27:42 +03001773 // input variables in the fragment shader can be also qualified as invariant
1774 if (!sh::CanBeInvariantESSL1(qualifier))
1775 {
1776 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1777 }
1778 }
1779 else
1780 {
1781 if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
1782 {
1783 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1784 }
Olli Etuaho37ad4742015-04-27 13:18:50 +03001785 }
1786}
1787
Olli Etuaho2a1e8f92017-07-14 11:49:36 +03001788bool TParseContext::isExtensionEnabled(TExtension extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001789{
Olli Etuaho2a1e8f92017-07-14 11:49:36 +03001790 return IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001791}
1792
Jamie Madillb98c3a82015-07-23 14:26:04 -04001793void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1794 const char *extName,
1795 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001796{
Geoff Lang197d5292018-04-25 14:29:00 -04001797 angle::pp::SourceLocation srcLoc;
Jamie Madill075edd82013-07-08 13:30:19 -04001798 srcLoc.file = loc.first_file;
1799 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001800 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001801}
1802
Jamie Madillb98c3a82015-07-23 14:26:04 -04001803void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1804 const char *name,
1805 const char *value,
1806 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001807{
Geoff Lang197d5292018-04-25 14:29:00 -04001808 angle::pp::SourceLocation srcLoc;
Jamie Madill075edd82013-07-08 13:30:19 -04001809 srcLoc.file = loc.first_file;
1810 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001811 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001812}
1813
Martin Radev4c4c8e72016-08-04 12:25:34 +03001814sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
Martin Radev802abe02016-08-04 17:48:32 +03001815{
Jamie Madill2f294c92017-11-20 14:47:26 -05001816 sh::WorkGroupSize result(-1);
Martin Radev802abe02016-08-04 17:48:32 +03001817 for (size_t i = 0u; i < result.size(); ++i)
1818 {
1819 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1820 {
1821 result[i] = 1;
1822 }
1823 else
1824 {
1825 result[i] = mComputeShaderLocalSize[i];
1826 }
1827 }
1828 return result;
1829}
1830
Olli Etuaho56229f12017-07-10 14:16:33 +03001831TIntermConstantUnion *TParseContext::addScalarLiteral(const TConstantUnion *constantUnion,
1832 const TSourceLoc &line)
1833{
1834 TIntermConstantUnion *node = new TIntermConstantUnion(
1835 constantUnion, TType(constantUnion->getType(), EbpUndefined, EvqConst));
1836 node->setLine(line);
1837 return node;
1838}
1839
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001840/////////////////////////////////////////////////////////////////////////////////
1841//
1842// Non-Errors.
1843//
1844/////////////////////////////////////////////////////////////////////////////////
1845
Jamie Madill5c097022014-08-20 16:38:32 -04001846const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
Olli Etuahofbb1c792018-01-19 16:26:59 +02001847 const ImmutableString &name,
Jamie Madill5c097022014-08-20 16:38:32 -04001848 const TSymbol *symbol)
1849{
Jamie Madill5c097022014-08-20 16:38:32 -04001850 if (!symbol)
1851 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02001852 error(location, "undeclared identifier", name);
Olli Etuaho0f684632017-07-13 12:42:15 +03001853 return nullptr;
Jamie Madill5c097022014-08-20 16:38:32 -04001854 }
Olli Etuaho0f684632017-07-13 12:42:15 +03001855
1856 if (!symbol->isVariable())
Jamie Madill5c097022014-08-20 16:38:32 -04001857 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02001858 error(location, "variable expected", name);
Olli Etuaho0f684632017-07-13 12:42:15 +03001859 return nullptr;
Jamie Madill5c097022014-08-20 16:38:32 -04001860 }
Olli Etuaho0f684632017-07-13 12:42:15 +03001861
1862 const TVariable *variable = static_cast<const TVariable *>(symbol);
1863
Olli Etuaho54a29ff2017-11-28 17:35:20 +02001864 if (variable->extension() != TExtension::UNDEFINED)
Jamie Madill5c097022014-08-20 16:38:32 -04001865 {
Olli Etuaho54a29ff2017-11-28 17:35:20 +02001866 checkCanUseExtension(location, variable->extension());
Jamie Madill5c097022014-08-20 16:38:32 -04001867 }
1868
Olli Etuaho0f684632017-07-13 12:42:15 +03001869 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1870 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
Olli Etuaho59c5b892018-04-03 11:44:50 +03001871 variable->getType().getQualifier() == EvqWorkGroupSize)
Olli Etuaho0f684632017-07-13 12:42:15 +03001872 {
1873 error(location,
1874 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1875 "gl_WorkGroupSize");
1876 }
Jamie Madill5c097022014-08-20 16:38:32 -04001877 return variable;
1878}
1879
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001880TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
Olli Etuahofbb1c792018-01-19 16:26:59 +02001881 const ImmutableString &name,
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001882 const TSymbol *symbol)
1883{
1884 const TVariable *variable = getNamedVariable(location, name, symbol);
1885
Olli Etuaho0f684632017-07-13 12:42:15 +03001886 if (!variable)
1887 {
1888 TIntermTyped *node = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
1889 node->setLine(location);
1890 return node;
1891 }
1892
Jiawei Shao8e4b3552017-08-30 14:20:58 +08001893 const TType &variableType = variable->getType();
Jamie Madill50cf2be2018-06-15 09:46:57 -04001894 TIntermTyped *node = nullptr;
Olli Etuaho56229f12017-07-10 14:16:33 +03001895
Olli Etuahoea22b7a2018-01-04 17:09:11 +02001896 if (variable->getConstPointer() && variableType.canReplaceWithConstantUnion())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001897 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001898 const TConstantUnion *constArray = variable->getConstPointer();
Jiawei Shao8e4b3552017-08-30 14:20:58 +08001899 node = new TIntermConstantUnion(constArray, variableType);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001900 }
Jiawei Shao8e4b3552017-08-30 14:20:58 +08001901 else if (variableType.getQualifier() == EvqWorkGroupSize && mComputeShaderLocalSizeDeclared)
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001902 {
1903 // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
1904 // needs to be added to the AST as a constant and not as a symbol.
1905 sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
1906 TConstantUnion *constArray = new TConstantUnion[3];
1907 for (size_t i = 0; i < 3; ++i)
1908 {
1909 constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
1910 }
1911
Jiawei Shao8e4b3552017-08-30 14:20:58 +08001912 ASSERT(variableType.getBasicType() == EbtUInt);
1913 ASSERT(variableType.getObjectSize() == 3);
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001914
Jiawei Shao8e4b3552017-08-30 14:20:58 +08001915 TType type(variableType);
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001916 type.setQualifier(EvqConst);
Olli Etuaho56229f12017-07-10 14:16:33 +03001917 node = new TIntermConstantUnion(constArray, type);
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001918 }
Jiawei Shao8e4b3552017-08-30 14:20:58 +08001919 else if ((mGeometryShaderInputPrimitiveType != EptUndefined) &&
1920 (variableType.getQualifier() == EvqPerVertexIn))
Jiawei Shaod8105a02017-08-08 09:54:36 +08001921 {
Olli Etuaho94bbed12018-03-20 14:44:53 +02001922 ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr);
1923 node = new TIntermSymbol(symbolTable.getGlInVariableWithArraySize());
Jiawei Shaod8105a02017-08-08 09:54:36 +08001924 }
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001925 else
1926 {
Olli Etuaho195be942017-12-04 23:40:14 +02001927 node = new TIntermSymbol(variable);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001928 }
Olli Etuaho56229f12017-07-10 14:16:33 +03001929 ASSERT(node != nullptr);
1930 node->setLine(location);
1931 return node;
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001932}
1933
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001934// Initializers show up in several places in the grammar. Have one set of
1935// code to handle them here.
1936//
Olli Etuaho914b79a2017-06-19 16:03:19 +03001937// Returns true on success.
Jamie Madillb98c3a82015-07-23 14:26:04 -04001938bool TParseContext::executeInitializer(const TSourceLoc &line,
Olli Etuahofbb1c792018-01-19 16:26:59 +02001939 const ImmutableString &identifier,
Olli Etuahob60d30f2018-01-16 12:31:06 +02001940 TType *type,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001941 TIntermTyped *initializer,
Olli Etuaho13389b62016-10-16 11:48:18 +01001942 TIntermBinary **initNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001943{
Olli Etuaho13389b62016-10-16 11:48:18 +01001944 ASSERT(initNode != nullptr);
1945 ASSERT(*initNode == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001946
Olli Etuahob60d30f2018-01-16 12:31:06 +02001947 if (type->isUnsizedArray())
Olli Etuaho376f1b52015-04-13 13:23:41 +03001948 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03001949 // In case initializer is not an array or type has more dimensions than initializer, this
1950 // will default to setting array sizes to 1. We have not checked yet whether the initializer
1951 // actually is an array or not. Having a non-array initializer for an unsized array will
1952 // result in an error later, so we don't generate an error message here.
Kai Ninomiya57ea5332017-11-22 14:04:48 -08001953 auto *arraySizes = initializer->getType().getArraySizes();
Olli Etuahob60d30f2018-01-16 12:31:06 +02001954 type->sizeUnsizedArrays(arraySizes);
1955 }
1956
1957 const TQualifier qualifier = type->getQualifier();
1958
1959 bool constError = false;
1960 if (qualifier == EvqConst)
1961 {
1962 if (EvqConst != initializer->getType().getQualifier())
1963 {
Olli Etuaho72e35892018-06-20 11:43:08 +03001964 TInfoSinkBase reasonStream;
1965 reasonStream << "assigning non-constant to '" << *type << "'";
1966 error(line, reasonStream.c_str(), "=");
Olli Etuahob60d30f2018-01-16 12:31:06 +02001967
1968 // We're still going to declare the variable to avoid extra error messages.
1969 type->setQualifier(EvqTemporary);
1970 constError = true;
1971 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03001972 }
Olli Etuaho195be942017-12-04 23:40:14 +02001973
1974 TVariable *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +03001975 if (!declareVariable(line, identifier, type, &variable))
1976 {
Olli Etuaho914b79a2017-06-19 16:03:19 +03001977 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001978 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001979
Olli Etuahob60d30f2018-01-16 12:31:06 +02001980 if (constError)
1981 {
1982 return false;
1983 }
1984
Olli Etuahob0c645e2015-05-12 14:25:36 +03001985 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001986 if (symbolTable.atGlobalLevel() &&
Olli Etuahoa2d98142017-12-15 14:18:55 +02001987 !ValidateGlobalInitializer(initializer, mShaderVersion, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001988 {
1989 // Error message does not completely match behavior with ESSL 1.00, but
1990 // we want to steer developers towards only using constant expressions.
1991 error(line, "global variable initializers must be constant expressions", "=");
Olli Etuaho914b79a2017-06-19 16:03:19 +03001992 return false;
Olli Etuahob0c645e2015-05-12 14:25:36 +03001993 }
1994 if (globalInitWarning)
1995 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001996 warning(
1997 line,
1998 "global variable initializers should be constant expressions "
1999 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
2000 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03002001 }
2002
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002003 // identifier must be of type constant, a global, or a temporary
Arun Patole7e7e68d2015-05-22 12:02:25 +05302004 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
2005 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002006 error(line, " cannot initialize this type of qualifier ",
2007 variable->getType().getQualifierString());
Olli Etuaho914b79a2017-06-19 16:03:19 +03002008 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002009 }
Olli Etuahob60d30f2018-01-16 12:31:06 +02002010
2011 TIntermSymbol *intermSymbol = new TIntermSymbol(variable);
2012 intermSymbol->setLine(line);
2013
2014 if (!binaryOpCommonCheck(EOpInitialize, intermSymbol, initializer, line))
2015 {
Olli Etuaho72e35892018-06-20 11:43:08 +03002016 assignError(line, "=", variable->getType(), initializer->getType());
Olli Etuahob60d30f2018-01-16 12:31:06 +02002017 return false;
2018 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002019
Arun Patole7e7e68d2015-05-22 12:02:25 +05302020 if (qualifier == EvqConst)
2021 {
Olli Etuahoea22b7a2018-01-04 17:09:11 +02002022 // Save the constant folded value to the variable if possible.
2023 const TConstantUnion *constArray = initializer->getConstantValue();
2024 if (constArray)
Arun Patole7e7e68d2015-05-22 12:02:25 +05302025 {
Olli Etuahoea22b7a2018-01-04 17:09:11 +02002026 variable->shareConstPointer(constArray);
2027 if (initializer->getType().canReplaceWithConstantUnion())
Olli Etuahob1edc4f2015-11-02 17:20:03 +02002028 {
Olli Etuaho914b79a2017-06-19 16:03:19 +03002029 ASSERT(*initNode == nullptr);
2030 return true;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02002031 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00002032 }
2033 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02002034
Olli Etuahob60d30f2018-01-16 12:31:06 +02002035 *initNode = new TIntermBinary(EOpInitialize, intermSymbol, initializer);
Olli Etuaho94bbed12018-03-20 14:44:53 +02002036 markStaticReadIfSymbol(initializer);
Olli Etuahob60d30f2018-01-16 12:31:06 +02002037 (*initNode)->setLine(line);
Olli Etuaho914b79a2017-06-19 16:03:19 +03002038 return true;
2039}
2040
2041TIntermNode *TParseContext::addConditionInitializer(const TPublicType &pType,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002042 const ImmutableString &identifier,
Olli Etuaho914b79a2017-06-19 16:03:19 +03002043 TIntermTyped *initializer,
2044 const TSourceLoc &loc)
2045{
2046 checkIsScalarBool(loc, pType);
2047 TIntermBinary *initNode = nullptr;
Olli Etuahob60d30f2018-01-16 12:31:06 +02002048 TType *type = new TType(pType);
Olli Etuaho55bde912017-10-25 13:41:13 +03002049 if (executeInitializer(loc, identifier, type, initializer, &initNode))
Olli Etuaho914b79a2017-06-19 16:03:19 +03002050 {
2051 // The initializer is valid. The init condition needs to have a node - either the
2052 // initializer node, or a constant node in case the initialized variable is const and won't
2053 // be recorded in the AST.
2054 if (initNode == nullptr)
2055 {
2056 return initializer;
2057 }
2058 else
2059 {
2060 TIntermDeclaration *declaration = new TIntermDeclaration();
2061 declaration->appendDeclarator(initNode);
2062 return declaration;
2063 }
2064 }
2065 return nullptr;
2066}
2067
2068TIntermNode *TParseContext::addLoop(TLoopType type,
2069 TIntermNode *init,
2070 TIntermNode *cond,
2071 TIntermTyped *expr,
2072 TIntermNode *body,
2073 const TSourceLoc &line)
2074{
2075 TIntermNode *node = nullptr;
2076 TIntermTyped *typedCond = nullptr;
2077 if (cond)
2078 {
Olli Etuaho94bbed12018-03-20 14:44:53 +02002079 markStaticReadIfSymbol(cond);
Olli Etuaho914b79a2017-06-19 16:03:19 +03002080 typedCond = cond->getAsTyped();
2081 }
Olli Etuaho94bbed12018-03-20 14:44:53 +02002082 if (expr)
2083 {
2084 markStaticReadIfSymbol(expr);
2085 }
2086 // In case the loop body was not parsed as a block and contains a statement that simply refers
2087 // to a variable, we need to mark it as statically used.
2088 if (body)
2089 {
2090 markStaticReadIfSymbol(body);
2091 }
Olli Etuaho914b79a2017-06-19 16:03:19 +03002092 if (cond == nullptr || typedCond)
2093 {
Olli Etuahocce89652017-06-19 16:04:09 +03002094 if (type == ELoopDoWhile)
2095 {
2096 checkIsScalarBool(line, typedCond);
2097 }
2098 // In the case of other loops, it was checked before that the condition is a scalar boolean.
2099 ASSERT(mDiagnostics->numErrors() > 0 || typedCond == nullptr ||
2100 (typedCond->getBasicType() == EbtBool && !typedCond->isArray() &&
2101 !typedCond->isVector()));
2102
Olli Etuaho3ec75682017-07-05 17:02:55 +03002103 node = new TIntermLoop(type, init, typedCond, expr, EnsureBlock(body));
Olli Etuaho914b79a2017-06-19 16:03:19 +03002104 node->setLine(line);
2105 return node;
2106 }
2107
Olli Etuahocce89652017-06-19 16:04:09 +03002108 ASSERT(type != ELoopDoWhile);
2109
Olli Etuaho914b79a2017-06-19 16:03:19 +03002110 TIntermDeclaration *declaration = cond->getAsDeclarationNode();
2111 ASSERT(declaration);
2112 TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode();
2113 ASSERT(declarator->getLeft()->getAsSymbolNode());
2114
2115 // The condition is a declaration. In the AST representation we don't support declarations as
2116 // loop conditions. Wrap the loop to a block that declares the condition variable and contains
2117 // the loop.
2118 TIntermBlock *block = new TIntermBlock();
2119
2120 TIntermDeclaration *declareCondition = new TIntermDeclaration();
2121 declareCondition->appendDeclarator(declarator->getLeft()->deepCopy());
2122 block->appendStatement(declareCondition);
2123
2124 TIntermBinary *conditionInit = new TIntermBinary(EOpAssign, declarator->getLeft()->deepCopy(),
2125 declarator->getRight()->deepCopy());
Olli Etuaho3ec75682017-07-05 17:02:55 +03002126 TIntermLoop *loop = new TIntermLoop(type, init, conditionInit, expr, EnsureBlock(body));
Olli Etuaho914b79a2017-06-19 16:03:19 +03002127 block->appendStatement(loop);
2128 loop->setLine(line);
2129 block->setLine(line);
2130 return block;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002131}
2132
Olli Etuahocce89652017-06-19 16:04:09 +03002133TIntermNode *TParseContext::addIfElse(TIntermTyped *cond,
2134 TIntermNodePair code,
2135 const TSourceLoc &loc)
2136{
Olli Etuaho56229f12017-07-10 14:16:33 +03002137 bool isScalarBool = checkIsScalarBool(loc, cond);
Olli Etuaho94bbed12018-03-20 14:44:53 +02002138 // In case the conditional statements were not parsed as blocks and contain a statement that
2139 // simply refers to a variable, we need to mark them as statically used.
2140 if (code.node1)
2141 {
2142 markStaticReadIfSymbol(code.node1);
2143 }
2144 if (code.node2)
2145 {
2146 markStaticReadIfSymbol(code.node2);
2147 }
Olli Etuahocce89652017-06-19 16:04:09 +03002148
2149 // For compile time constant conditions, prune the code now.
Olli Etuaho56229f12017-07-10 14:16:33 +03002150 if (isScalarBool && cond->getAsConstantUnion())
Olli Etuahocce89652017-06-19 16:04:09 +03002151 {
2152 if (cond->getAsConstantUnion()->getBConst(0) == true)
2153 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03002154 return EnsureBlock(code.node1);
Olli Etuahocce89652017-06-19 16:04:09 +03002155 }
2156 else
2157 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03002158 return EnsureBlock(code.node2);
Olli Etuahocce89652017-06-19 16:04:09 +03002159 }
2160 }
2161
Olli Etuaho3ec75682017-07-05 17:02:55 +03002162 TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2));
Olli Etuaho94bbed12018-03-20 14:44:53 +02002163 markStaticReadIfSymbol(cond);
Olli Etuahocce89652017-06-19 16:04:09 +03002164 node->setLine(loc);
2165
2166 return node;
2167}
2168
Olli Etuaho0e3aee32016-10-27 12:56:38 +01002169void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
2170{
2171 checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
2172 typeSpecifier->getBasicType());
2173
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002174 if (mShaderVersion < 300 && typeSpecifier->isArray())
Olli Etuaho0e3aee32016-10-27 12:56:38 +01002175 {
2176 error(typeSpecifier->getLine(), "not supported", "first-class array");
2177 typeSpecifier->clearArrayness();
2178 }
2179}
2180
Martin Radev70866b82016-07-22 15:27:42 +03002181TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302182 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002183{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002184 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002185
Martin Radev70866b82016-07-22 15:27:42 +03002186 TPublicType returnType = typeSpecifier;
2187 returnType.qualifier = typeQualifier.qualifier;
2188 returnType.invariant = typeQualifier.invariant;
2189 returnType.layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03002190 returnType.memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03002191 returnType.precision = typeSpecifier.precision;
2192
2193 if (typeQualifier.precision != EbpUndefined)
2194 {
2195 returnType.precision = typeQualifier.precision;
2196 }
2197
Martin Radev4a9cd802016-09-01 16:51:51 +03002198 checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
2199 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03002200
Martin Radev4a9cd802016-09-01 16:51:51 +03002201 checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
2202 typeSpecifier.getLine());
Martin Radev70866b82016-07-22 15:27:42 +03002203
Martin Radev4a9cd802016-09-01 16:51:51 +03002204 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002205
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002206 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002207 {
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002208 if (typeSpecifier.isArray())
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03002209 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002210 error(typeSpecifier.getLine(), "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03002211 returnType.clearArrayness();
2212 }
2213
Martin Radev70866b82016-07-22 15:27:42 +03002214 if (returnType.qualifier == EvqAttribute &&
Martin Radev4a9cd802016-09-01 16:51:51 +03002215 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002216 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002217 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03002218 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002219 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002220
Martin Radev70866b82016-07-22 15:27:42 +03002221 if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
Martin Radev4a9cd802016-09-01 16:51:51 +03002222 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002223 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002224 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03002225 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002226 }
2227 }
2228 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002229 {
Martin Radev70866b82016-07-22 15:27:42 +03002230 if (!returnType.layoutQualifier.isEmpty())
Olli Etuahoabb0c382015-07-13 12:01:12 +03002231 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002232 checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03002233 }
Martin Radev70866b82016-07-22 15:27:42 +03002234 if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
2235 returnType.qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002236 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002237 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
2238 typeSpecifier.getLine());
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00002239 }
Martin Radev70866b82016-07-22 15:27:42 +03002240 if (returnType.qualifier == EvqComputeIn)
Martin Radev802abe02016-08-04 17:48:32 +03002241 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002242 error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
Martin Radev802abe02016-08-04 17:48:32 +03002243 "in");
Martin Radev802abe02016-08-04 17:48:32 +03002244 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00002245 }
2246
2247 return returnType;
2248}
2249
Olli Etuaho856c4972016-08-08 11:38:39 +03002250void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
2251 const TPublicType &type,
2252 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03002253{
2254 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
Martin Radev4a9cd802016-09-01 16:51:51 +03002255 if (type.getBasicType() == EbtBool)
Olli Etuahocc36b982015-07-10 14:14:18 +03002256 {
2257 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002258 }
2259
2260 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
2261 switch (qualifier)
2262 {
2263 case EvqVertexIn:
2264 // ESSL 3.00 section 4.3.4
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002265 if (type.isArray())
Olli Etuahocc36b982015-07-10 14:14:18 +03002266 {
2267 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002268 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002269 // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03002270 return;
2271 case EvqFragmentOut:
2272 // ESSL 3.00 section 4.3.6
Martin Radev4a9cd802016-09-01 16:51:51 +03002273 if (type.typeSpecifierNonArray.isMatrix())
Olli Etuahocc36b982015-07-10 14:14:18 +03002274 {
2275 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002276 }
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002277 // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
Olli Etuahocc36b982015-07-10 14:14:18 +03002278 return;
2279 default:
2280 break;
2281 }
2282
2283 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
2284 // restrictions.
2285 bool typeContainsIntegers =
Martin Radev4a9cd802016-09-01 16:51:51 +03002286 (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
2287 type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
Olli Etuahocc36b982015-07-10 14:14:18 +03002288 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
2289 {
2290 error(qualifierLocation, "must use 'flat' interpolation here",
2291 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002292 }
2293
Martin Radev4a9cd802016-09-01 16:51:51 +03002294 if (type.getBasicType() == EbtStruct)
Olli Etuahocc36b982015-07-10 14:14:18 +03002295 {
2296 // ESSL 3.00 sections 4.3.4 and 4.3.6.
2297 // These restrictions are only implied by the ESSL 3.00 spec, but
2298 // the ESSL 3.10 spec lists these restrictions explicitly.
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002299 if (type.isArray())
Olli Etuahocc36b982015-07-10 14:14:18 +03002300 {
2301 error(qualifierLocation, "cannot be an array of structures",
2302 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002303 }
2304 if (type.isStructureContainingArrays())
2305 {
2306 error(qualifierLocation, "cannot be a structure containing an array",
2307 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002308 }
2309 if (type.isStructureContainingType(EbtStruct))
2310 {
2311 error(qualifierLocation, "cannot be a structure containing a structure",
2312 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002313 }
2314 if (type.isStructureContainingType(EbtBool))
2315 {
2316 error(qualifierLocation, "cannot be a structure containing a bool",
2317 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03002318 }
2319 }
2320}
2321
Martin Radev2cc85b32016-08-05 16:22:53 +03002322void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
2323{
2324 if (qualifier.getType() == QtStorage)
2325 {
2326 const TStorageQualifierWrapper &storageQualifier =
2327 static_cast<const TStorageQualifierWrapper &>(qualifier);
2328 if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
2329 !symbolTable.atGlobalLevel())
2330 {
2331 error(storageQualifier.getLine(),
2332 "Local variables can only use the const storage qualifier.",
Olli Etuaho1a3bbaa2018-01-25 11:41:31 +02002333 storageQualifier.getQualifierString());
Martin Radev2cc85b32016-08-05 16:22:53 +03002334 }
2335 }
2336}
2337
Olli Etuaho43364892017-02-13 16:00:12 +00002338void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
Martin Radev2cc85b32016-08-05 16:22:53 +03002339 const TSourceLoc &location)
2340{
Jiajia Qinbc585152017-06-23 15:42:17 +08002341 const std::string reason(
2342 "Only allowed with shader storage blocks, variables declared within shader storage blocks "
2343 "and variables declared as image types.");
Martin Radev2cc85b32016-08-05 16:22:53 +03002344 if (memoryQualifier.readonly)
2345 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002346 error(location, reason.c_str(), "readonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03002347 }
2348 if (memoryQualifier.writeonly)
2349 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002350 error(location, reason.c_str(), "writeonly");
Martin Radev2cc85b32016-08-05 16:22:53 +03002351 }
Martin Radev049edfa2016-11-11 14:35:37 +02002352 if (memoryQualifier.coherent)
2353 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002354 error(location, reason.c_str(), "coherent");
Martin Radev049edfa2016-11-11 14:35:37 +02002355 }
2356 if (memoryQualifier.restrictQualifier)
2357 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002358 error(location, reason.c_str(), "restrict");
Martin Radev049edfa2016-11-11 14:35:37 +02002359 }
2360 if (memoryQualifier.volatileQualifier)
2361 {
Jiajia Qinbc585152017-06-23 15:42:17 +08002362 error(location, reason.c_str(), "volatile");
Martin Radev049edfa2016-11-11 14:35:37 +02002363 }
Martin Radev2cc85b32016-08-05 16:22:53 +03002364}
2365
jchen104cdac9e2017-05-08 11:01:20 +08002366// Make sure there is no offset overlapping, and store the newly assigned offset to "type" in
2367// intermediate tree.
Olli Etuaho55bc9052017-10-25 17:33:06 +03002368void TParseContext::checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend,
2369 const TSourceLoc &loc,
2370 TType *type)
jchen104cdac9e2017-05-08 11:01:20 +08002371{
Olli Etuaho55bc9052017-10-25 17:33:06 +03002372 const size_t size = type->isArray() ? kAtomicCounterArrayStride * type->getArraySizeProduct()
2373 : kAtomicCounterSize;
2374 TLayoutQualifier layoutQualifier = type->getLayoutQualifier();
2375 auto &bindingState = mAtomicCounterBindingStates[layoutQualifier.binding];
jchen104cdac9e2017-05-08 11:01:20 +08002376 int offset;
Olli Etuaho55bc9052017-10-25 17:33:06 +03002377 if (layoutQualifier.offset == -1 || forceAppend)
jchen104cdac9e2017-05-08 11:01:20 +08002378 {
2379 offset = bindingState.appendSpan(size);
2380 }
2381 else
2382 {
Olli Etuaho55bc9052017-10-25 17:33:06 +03002383 offset = bindingState.insertSpan(layoutQualifier.offset, size);
jchen104cdac9e2017-05-08 11:01:20 +08002384 }
2385 if (offset == -1)
2386 {
2387 error(loc, "Offset overlapping", "atomic counter");
2388 return;
2389 }
Olli Etuaho55bc9052017-10-25 17:33:06 +03002390 layoutQualifier.offset = offset;
2391 type->setLayoutQualifier(layoutQualifier);
jchen104cdac9e2017-05-08 11:01:20 +08002392}
2393
Enrico Galliee7ffd92018-12-13 14:07:52 -08002394void TParseContext::checkAtomicCounterOffsetAlignment(const TSourceLoc &location, const TType &type)
2395{
2396 TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
2397
2398 // OpenGL ES 3.1 Table 6.5, Atomic counter offset must be a multiple of 4
2399 if (layoutQualifier.offset % 4 != 0)
2400 {
2401 error(location, "Offset must be multiple of 4", "atomic counter");
2402 }
2403}
2404
Olli Etuaho454c34c2017-10-25 16:35:56 +03002405void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002406 const ImmutableString &token,
Olli Etuaho454c34c2017-10-25 16:35:56 +03002407 TType *type)
2408{
2409 if (IsGeometryShaderInput(mShaderType, type->getQualifier()))
2410 {
2411 if (type->isArray() && type->getOutermostArraySize() == 0u)
2412 {
2413 // Set size for the unsized geometry shader inputs if they are declared after a valid
2414 // input primitive declaration.
2415 if (mGeometryShaderInputPrimitiveType != EptUndefined)
2416 {
Olli Etuaho94bbed12018-03-20 14:44:53 +02002417 ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr);
Olli Etuahoc74ec1a2018-01-09 15:23:28 +02002418 type->sizeOutermostUnsizedArray(
Olli Etuaho94bbed12018-03-20 14:44:53 +02002419 symbolTable.getGlInVariableWithArraySize()->getType().getOutermostArraySize());
Olli Etuaho454c34c2017-10-25 16:35:56 +03002420 }
2421 else
2422 {
2423 // [GLSL ES 3.2 SPEC Chapter 4.4.1.2]
2424 // An input can be declared without an array size if there is a previous layout
2425 // which specifies the size.
2426 error(location,
2427 "Missing a valid input primitive declaration before declaring an unsized "
2428 "array input",
2429 token);
2430 }
2431 }
2432 else if (type->isArray())
2433 {
2434 setGeometryShaderInputArraySize(type->getOutermostArraySize(), location);
2435 }
2436 else
2437 {
2438 error(location, "Geometry shader input variable must be declared as an array", token);
2439 }
2440 }
2441}
2442
Olli Etuaho13389b62016-10-16 11:48:18 +01002443TIntermDeclaration *TParseContext::parseSingleDeclaration(
2444 TPublicType &publicType,
2445 const TSourceLoc &identifierOrTypeLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002446 const ImmutableString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04002447{
Olli Etuahob60d30f2018-01-16 12:31:06 +02002448 TType *type = new TType(publicType);
Kenneth Russellbccc65d2016-07-19 16:48:43 -07002449
Olli Etuahofbb1c792018-01-19 16:26:59 +02002450 checkGeometryShaderInputAndSetArraySize(identifierOrTypeLocation, identifier, type);
Jiawei Shao8e4b3552017-08-30 14:20:58 +08002451
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002452 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2453 identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002454
Jamie Madill50cf2be2018-06-15 09:46:57 -04002455 bool emptyDeclaration = (identifier == "");
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002456 mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration;
Olli Etuahofa33d582015-04-09 14:33:12 +03002457
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002458 TIntermSymbol *symbol = nullptr;
Olli Etuahobab4c082015-04-24 16:38:49 +03002459 if (emptyDeclaration)
2460 {
Olli Etuahob60d30f2018-01-16 12:31:06 +02002461 emptyDeclarationErrorCheck(*type, identifierOrTypeLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002462 // In most cases we don't need to create a symbol node for an empty declaration.
2463 // But if the empty declaration is declaring a struct type, the symbol node will store that.
Olli Etuahob60d30f2018-01-16 12:31:06 +02002464 if (type->getBasicType() == EbtStruct)
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002465 {
Olli Etuaho195be942017-12-04 23:40:14 +02002466 TVariable *emptyVariable =
Jamie Madillb779b122018-06-20 11:46:43 -04002467 new TVariable(&symbolTable, kEmptyImmutableString, type, SymbolType::Empty);
Olli Etuaho195be942017-12-04 23:40:14 +02002468 symbol = new TIntermSymbol(emptyVariable);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002469 }
jchen104cdac9e2017-05-08 11:01:20 +08002470 else if (IsAtomicCounter(publicType.getBasicType()))
2471 {
2472 setAtomicCounterBindingDefaultOffset(publicType, identifierOrTypeLocation);
2473 }
Olli Etuahobab4c082015-04-24 16:38:49 +03002474 }
2475 else
Jamie Madill60ed9812013-06-06 11:56:46 -04002476 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002477 nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002478
Olli Etuahob60d30f2018-01-16 12:31:06 +02002479 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, type);
Jamie Madill60ed9812013-06-06 11:56:46 -04002480
Enrico Galliee7ffd92018-12-13 14:07:52 -08002481 if (IsAtomicCounter(type->getBasicType()))
2482 {
2483 checkAtomicCounterOffsetDoesNotOverlap(false, identifierOrTypeLocation, type);
2484
2485 checkAtomicCounterOffsetAlignment(identifierOrTypeLocation, *type);
2486 }
jchen104cdac9e2017-05-08 11:01:20 +08002487
Olli Etuaho2935c582015-04-08 14:32:06 +03002488 TVariable *variable = nullptr;
Olli Etuaho195be942017-12-04 23:40:14 +02002489 if (declareVariable(identifierOrTypeLocation, identifier, type, &variable))
Olli Etuaho13389b62016-10-16 11:48:18 +01002490 {
Olli Etuaho195be942017-12-04 23:40:14 +02002491 symbol = new TIntermSymbol(variable);
Olli Etuaho13389b62016-10-16 11:48:18 +01002492 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002493 }
2494
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002495 TIntermDeclaration *declaration = new TIntermDeclaration();
2496 declaration->setLine(identifierOrTypeLocation);
2497 if (symbol)
2498 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002499 symbol->setLine(identifierOrTypeLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002500 declaration->appendDeclarator(symbol);
2501 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002502 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002503}
2504
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002505TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(
2506 TPublicType &elementType,
2507 const TSourceLoc &identifierLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002508 const ImmutableString &identifier,
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002509 const TSourceLoc &indexLocation,
2510 const TVector<unsigned int> &arraySizes)
Jamie Madill60ed9812013-06-06 11:56:46 -04002511{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002512 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002513
Olli Etuaho55bde912017-10-25 13:41:13 +03002514 declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier,
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002515 identifierLocation);
2516
Olli Etuaho55bde912017-10-25 13:41:13 +03002517 nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002518
Olli Etuaho55bde912017-10-25 13:41:13 +03002519 checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
Jamie Madill60ed9812013-06-06 11:56:46 -04002520
Olli Etuahob60d30f2018-01-16 12:31:06 +02002521 TType *arrayType = new TType(elementType);
2522 arrayType->makeArrays(arraySizes);
Jamie Madill60ed9812013-06-06 11:56:46 -04002523
Olli Etuahofbb1c792018-01-19 16:26:59 +02002524 checkGeometryShaderInputAndSetArraySize(indexLocation, identifier, arrayType);
Olli Etuaho55bde912017-10-25 13:41:13 +03002525
Olli Etuahob60d30f2018-01-16 12:31:06 +02002526 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, arrayType);
Olli Etuaho55bde912017-10-25 13:41:13 +03002527
Enrico Galliee7ffd92018-12-13 14:07:52 -08002528 if (IsAtomicCounter(arrayType->getBasicType()))
2529 {
2530 checkAtomicCounterOffsetDoesNotOverlap(false, identifierLocation, arrayType);
2531
2532 checkAtomicCounterOffsetAlignment(identifierLocation, *arrayType);
2533 }
jchen104cdac9e2017-05-08 11:01:20 +08002534
Olli Etuaho13389b62016-10-16 11:48:18 +01002535 TIntermDeclaration *declaration = new TIntermDeclaration();
2536 declaration->setLine(identifierLocation);
2537
Olli Etuaho195be942017-12-04 23:40:14 +02002538 TVariable *variable = nullptr;
2539 if (declareVariable(identifierLocation, identifier, arrayType, &variable))
Olli Etuaho13389b62016-10-16 11:48:18 +01002540 {
Olli Etuaho195be942017-12-04 23:40:14 +02002541 TIntermSymbol *symbol = new TIntermSymbol(variable);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002542 symbol->setLine(identifierLocation);
Olli Etuaho13389b62016-10-16 11:48:18 +01002543 declaration->appendDeclarator(symbol);
2544 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002545
Olli Etuaho13389b62016-10-16 11:48:18 +01002546 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002547}
2548
Olli Etuaho13389b62016-10-16 11:48:18 +01002549TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
2550 const TSourceLoc &identifierLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002551 const ImmutableString &identifier,
Olli Etuaho13389b62016-10-16 11:48:18 +01002552 const TSourceLoc &initLocation,
2553 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04002554{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002555 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002556
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002557 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2558 identifierLocation);
2559
2560 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04002561
Olli Etuaho13389b62016-10-16 11:48:18 +01002562 TIntermDeclaration *declaration = new TIntermDeclaration();
2563 declaration->setLine(identifierLocation);
2564
2565 TIntermBinary *initNode = nullptr;
Olli Etuahob60d30f2018-01-16 12:31:06 +02002566 TType *type = new TType(publicType);
Olli Etuaho55bde912017-10-25 13:41:13 +03002567 if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04002568 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002569 if (initNode)
2570 {
2571 declaration->appendDeclarator(initNode);
2572 }
Jamie Madill60ed9812013-06-06 11:56:46 -04002573 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002574 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04002575}
2576
Olli Etuaho13389b62016-10-16 11:48:18 +01002577TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
Olli Etuaho55bde912017-10-25 13:41:13 +03002578 TPublicType &elementType,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002579 const TSourceLoc &identifierLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002580 const ImmutableString &identifier,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002581 const TSourceLoc &indexLocation,
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002582 const TVector<unsigned int> &arraySizes,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002583 const TSourceLoc &initLocation,
2584 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002585{
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002586 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002587
Olli Etuaho55bde912017-10-25 13:41:13 +03002588 declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier,
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002589 identifierLocation);
2590
Olli Etuaho55bde912017-10-25 13:41:13 +03002591 nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002592
Olli Etuaho55bde912017-10-25 13:41:13 +03002593 checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002594
Olli Etuahob60d30f2018-01-16 12:31:06 +02002595 TType *arrayType = new TType(elementType);
2596 arrayType->makeArrays(arraySizes);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002597
Olli Etuaho13389b62016-10-16 11:48:18 +01002598 TIntermDeclaration *declaration = new TIntermDeclaration();
2599 declaration->setLine(identifierLocation);
2600
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002601 // initNode will correspond to the whole of "type b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002602 TIntermBinary *initNode = nullptr;
Olli Etuaho914b79a2017-06-19 16:03:19 +03002603 if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002604 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002605 if (initNode)
2606 {
2607 declaration->appendDeclarator(initNode);
2608 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002609 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002610
2611 return declaration;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002612}
2613
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002614TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
Martin Radev70866b82016-07-22 15:27:42 +03002615 const TTypeQualifierBuilder &typeQualifierBuilder,
2616 const TSourceLoc &identifierLoc,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002617 const ImmutableString &identifier,
Martin Radev70866b82016-07-22 15:27:42 +03002618 const TSymbol *symbol)
Jamie Madill47e3ec02014-08-20 16:38:33 -04002619{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002620 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002621
Martin Radev70866b82016-07-22 15:27:42 +03002622 if (!typeQualifier.invariant)
2623 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02002624 error(identifierLoc, "Expected invariant", identifier);
Martin Radev70866b82016-07-22 15:27:42 +03002625 return nullptr;
2626 }
2627 if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
2628 {
2629 return nullptr;
2630 }
Jamie Madill47e3ec02014-08-20 16:38:33 -04002631 if (!symbol)
2632 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02002633 error(identifierLoc, "undeclared identifier declared as invariant", identifier);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002634 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04002635 }
Martin Radev70866b82016-07-22 15:27:42 +03002636 if (!IsQualifierUnspecified(typeQualifier.qualifier))
Jamie Madill47e3ec02014-08-20 16:38:33 -04002637 {
Martin Radev70866b82016-07-22 15:27:42 +03002638 error(identifierLoc, "invariant declaration specifies qualifier",
2639 getQualifierString(typeQualifier.qualifier));
Jamie Madill47e3ec02014-08-20 16:38:33 -04002640 }
Martin Radev70866b82016-07-22 15:27:42 +03002641 if (typeQualifier.precision != EbpUndefined)
2642 {
2643 error(identifierLoc, "invariant declaration specifies precision",
2644 getPrecisionString(typeQualifier.precision));
2645 }
2646 if (!typeQualifier.layoutQualifier.isEmpty())
2647 {
2648 error(identifierLoc, "invariant declaration specifies layout", "'layout'");
2649 }
2650
2651 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
Olli Etuaho0f684632017-07-13 12:42:15 +03002652 if (!variable)
2653 {
2654 return nullptr;
2655 }
Martin Radev70866b82016-07-22 15:27:42 +03002656 const TType &type = variable->getType();
2657
2658 checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
2659 typeQualifier.line);
Olli Etuaho43364892017-02-13 16:00:12 +00002660 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev70866b82016-07-22 15:27:42 +03002661
Olli Etuaho76b2c382018-03-19 15:51:29 +02002662 symbolTable.addInvariantVarying(*variable);
Martin Radev70866b82016-07-22 15:27:42 +03002663
Olli Etuaho195be942017-12-04 23:40:14 +02002664 TIntermSymbol *intermSymbol = new TIntermSymbol(variable);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002665 intermSymbol->setLine(identifierLoc);
Martin Radev70866b82016-07-22 15:27:42 +03002666
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002667 return new TIntermInvariantDeclaration(intermSymbol, identifierLoc);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002668}
2669
Olli Etuaho13389b62016-10-16 11:48:18 +01002670void TParseContext::parseDeclarator(TPublicType &publicType,
2671 const TSourceLoc &identifierLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002672 const ImmutableString &identifier,
Olli Etuaho13389b62016-10-16 11:48:18 +01002673 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002674{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002675 // If the declaration starting this declarator list was empty (example: int,), some checks were
2676 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002677 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002678 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002679 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2680 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002681 }
2682
Olli Etuaho856c4972016-08-08 11:38:39 +03002683 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002684
Olli Etuahob60d30f2018-01-16 12:31:06 +02002685 TType *type = new TType(publicType);
Olli Etuaho454c34c2017-10-25 16:35:56 +03002686
Olli Etuahofbb1c792018-01-19 16:26:59 +02002687 checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, type);
Olli Etuaho454c34c2017-10-25 16:35:56 +03002688
Olli Etuahob60d30f2018-01-16 12:31:06 +02002689 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, type);
Olli Etuaho55bde912017-10-25 13:41:13 +03002690
Enrico Galliee7ffd92018-12-13 14:07:52 -08002691 if (IsAtomicCounter(type->getBasicType()))
2692 {
2693 checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, type);
2694
2695 checkAtomicCounterOffsetAlignment(identifierLocation, *type);
2696 }
Olli Etuaho55bc9052017-10-25 17:33:06 +03002697
Olli Etuaho195be942017-12-04 23:40:14 +02002698 TVariable *variable = nullptr;
2699 if (declareVariable(identifierLocation, identifier, type, &variable))
Olli Etuaho13389b62016-10-16 11:48:18 +01002700 {
Olli Etuaho195be942017-12-04 23:40:14 +02002701 TIntermSymbol *symbol = new TIntermSymbol(variable);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03002702 symbol->setLine(identifierLocation);
Olli Etuaho13389b62016-10-16 11:48:18 +01002703 declarationOut->appendDeclarator(symbol);
2704 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002705}
2706
Olli Etuaho55bde912017-10-25 13:41:13 +03002707void TParseContext::parseArrayDeclarator(TPublicType &elementType,
Olli Etuaho13389b62016-10-16 11:48:18 +01002708 const TSourceLoc &identifierLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002709 const ImmutableString &identifier,
Olli Etuaho13389b62016-10-16 11:48:18 +01002710 const TSourceLoc &arrayLocation,
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002711 const TVector<unsigned int> &arraySizes,
Olli Etuaho13389b62016-10-16 11:48:18 +01002712 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002713{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002714 // If the declaration starting this declarator list was empty (example: int,), some checks were
2715 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002716 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002717 {
Olli Etuaho55bde912017-10-25 13:41:13 +03002718 nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002719 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002720 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002721
Olli Etuaho55bde912017-10-25 13:41:13 +03002722 checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002723
Olli Etuaho55bde912017-10-25 13:41:13 +03002724 if (checkIsValidTypeAndQualifierForArray(arrayLocation, elementType))
Jamie Madill502d66f2013-06-20 11:55:52 -04002725 {
Olli Etuahob60d30f2018-01-16 12:31:06 +02002726 TType *arrayType = new TType(elementType);
2727 arrayType->makeArrays(arraySizes);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002728
Olli Etuahofbb1c792018-01-19 16:26:59 +02002729 checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, arrayType);
Olli Etuaho454c34c2017-10-25 16:35:56 +03002730
Olli Etuahob60d30f2018-01-16 12:31:06 +02002731 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, arrayType);
Olli Etuaho55bde912017-10-25 13:41:13 +03002732
Enrico Galliee7ffd92018-12-13 14:07:52 -08002733 if (IsAtomicCounter(arrayType->getBasicType()))
2734 {
2735 checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, arrayType);
2736
2737 checkAtomicCounterOffsetAlignment(identifierLocation, *arrayType);
2738 }
jchen104cdac9e2017-05-08 11:01:20 +08002739
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002740 TVariable *variable = nullptr;
Olli Etuaho195be942017-12-04 23:40:14 +02002741 if (declareVariable(identifierLocation, identifier, arrayType, &variable))
Olli Etuahod7ceaa12017-07-12 17:46:35 +03002742 {
Olli Etuaho195be942017-12-04 23:40:14 +02002743 TIntermSymbol *symbol = new TIntermSymbol(variable);
Olli Etuahod7ceaa12017-07-12 17:46:35 +03002744 symbol->setLine(identifierLocation);
2745 declarationOut->appendDeclarator(symbol);
2746 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002747 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002748}
2749
Olli Etuaho13389b62016-10-16 11:48:18 +01002750void TParseContext::parseInitDeclarator(const TPublicType &publicType,
2751 const TSourceLoc &identifierLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002752 const ImmutableString &identifier,
Olli Etuaho13389b62016-10-16 11:48:18 +01002753 const TSourceLoc &initLocation,
2754 TIntermTyped *initializer,
2755 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002756{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002757 // If the declaration starting this declarator list was empty (example: int,), some checks were
2758 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002759 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuahofa33d582015-04-09 14:33:12 +03002760 {
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002761 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2762 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuahofa33d582015-04-09 14:33:12 +03002763 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002764
Olli Etuaho856c4972016-08-08 11:38:39 +03002765 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002766
Olli Etuaho13389b62016-10-16 11:48:18 +01002767 TIntermBinary *initNode = nullptr;
Olli Etuahob60d30f2018-01-16 12:31:06 +02002768 TType *type = new TType(publicType);
Olli Etuaho55bde912017-10-25 13:41:13 +03002769 if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04002770 {
2771 //
2772 // build the intermediate representation
2773 //
Olli Etuaho13389b62016-10-16 11:48:18 +01002774 if (initNode)
Jamie Madill502d66f2013-06-20 11:55:52 -04002775 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002776 declarationOut->appendDeclarator(initNode);
Jamie Madill502d66f2013-06-20 11:55:52 -04002777 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002778 }
2779}
2780
Olli Etuaho55bde912017-10-25 13:41:13 +03002781void TParseContext::parseArrayInitDeclarator(const TPublicType &elementType,
Olli Etuaho13389b62016-10-16 11:48:18 +01002782 const TSourceLoc &identifierLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02002783 const ImmutableString &identifier,
Olli Etuaho13389b62016-10-16 11:48:18 +01002784 const TSourceLoc &indexLocation,
Olli Etuaho7881cfd2017-08-23 18:00:21 +03002785 const TVector<unsigned int> &arraySizes,
Olli Etuaho13389b62016-10-16 11:48:18 +01002786 const TSourceLoc &initLocation,
2787 TIntermTyped *initializer,
2788 TIntermDeclaration *declarationOut)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002789{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002790 // If the declaration starting this declarator list was empty (example: int,), some checks were
2791 // not performed.
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002792 if (mDeferredNonEmptyDeclarationErrorCheck)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002793 {
Olli Etuaho55bde912017-10-25 13:41:13 +03002794 nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
Olli Etuahobb7e5a72017-04-24 10:16:44 +03002795 mDeferredNonEmptyDeclarationErrorCheck = false;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002796 }
2797
Olli Etuaho55bde912017-10-25 13:41:13 +03002798 checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002799
Olli Etuaho55bde912017-10-25 13:41:13 +03002800 checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002801
Olli Etuahob60d30f2018-01-16 12:31:06 +02002802 TType *arrayType = new TType(elementType);
2803 arrayType->makeArrays(arraySizes);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002804
2805 // initNode will correspond to the whole of "b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002806 TIntermBinary *initNode = nullptr;
Olli Etuaho914b79a2017-06-19 16:03:19 +03002807 if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002808 {
2809 if (initNode)
2810 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002811 declarationOut->appendDeclarator(initNode);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002812 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002813 }
2814}
2815
Olli Etuahob8ee9dd2017-10-30 12:43:27 +02002816TIntermNode *TParseContext::addEmptyStatement(const TSourceLoc &location)
2817{
2818 // It's simpler to parse an empty statement as a constant expression rather than having a
2819 // different type of node just for empty statements, that will be pruned from the AST anyway.
2820 TIntermNode *node = CreateZeroNode(TType(EbtInt, EbpMedium));
2821 node->setLine(location);
2822 return node;
2823}
2824
jchen104cdac9e2017-05-08 11:01:20 +08002825void TParseContext::setAtomicCounterBindingDefaultOffset(const TPublicType &publicType,
2826 const TSourceLoc &location)
2827{
2828 const TLayoutQualifier &layoutQualifier = publicType.layoutQualifier;
2829 checkAtomicCounterBindingIsValid(location, layoutQualifier.binding);
2830 if (layoutQualifier.binding == -1 || layoutQualifier.offset == -1)
2831 {
2832 error(location, "Requires both binding and offset", "layout");
2833 return;
2834 }
2835 mAtomicCounterBindingStates[layoutQualifier.binding].setDefaultOffset(layoutQualifier.offset);
2836}
2837
Olli Etuahocce89652017-06-19 16:04:09 +03002838void TParseContext::parseDefaultPrecisionQualifier(const TPrecision precision,
2839 const TPublicType &type,
2840 const TSourceLoc &loc)
2841{
2842 if ((precision == EbpHigh) && (getShaderType() == GL_FRAGMENT_SHADER) &&
2843 !getFragmentPrecisionHigh())
2844 {
2845 error(loc, "precision is not supported in fragment shader", "highp");
2846 }
2847
2848 if (!CanSetDefaultPrecisionOnType(type))
2849 {
2850 error(loc, "illegal type argument for default precision qualifier",
2851 getBasicString(type.getBasicType()));
2852 return;
2853 }
2854 symbolTable.setDefaultPrecision(type.getBasicType(), precision);
2855}
2856
Shaob5cc1192017-07-06 10:47:20 +08002857bool TParseContext::checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier)
2858{
2859 switch (typeQualifier.layoutQualifier.primitiveType)
2860 {
2861 case EptLines:
2862 case EptLinesAdjacency:
2863 case EptTriangles:
2864 case EptTrianglesAdjacency:
2865 return typeQualifier.qualifier == EvqGeometryIn;
2866
2867 case EptLineStrip:
2868 case EptTriangleStrip:
2869 return typeQualifier.qualifier == EvqGeometryOut;
2870
2871 case EptPoints:
2872 return true;
2873
2874 default:
2875 UNREACHABLE();
2876 return false;
2877 }
2878}
2879
Jiawei Shao8e4b3552017-08-30 14:20:58 +08002880void TParseContext::setGeometryShaderInputArraySize(unsigned int inputArraySize,
2881 const TSourceLoc &line)
Jiawei Shaod8105a02017-08-08 09:54:36 +08002882{
Olli Etuaho94bbed12018-03-20 14:44:53 +02002883 if (!symbolTable.setGlInArraySize(inputArraySize))
Jiawei Shao8e4b3552017-08-30 14:20:58 +08002884 {
2885 error(line,
2886 "Array size or input primitive declaration doesn't match the size of earlier sized "
2887 "array inputs.",
2888 "layout");
2889 }
Jiawei Shaod8105a02017-08-08 09:54:36 +08002890}
2891
Shaob5cc1192017-07-06 10:47:20 +08002892bool TParseContext::parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier)
2893{
2894 ASSERT(typeQualifier.qualifier == EvqGeometryIn);
2895
2896 const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
2897
2898 if (layoutQualifier.maxVertices != -1)
2899 {
2900 error(typeQualifier.line,
2901 "max_vertices can only be declared in 'out' layout in a geometry shader", "layout");
2902 return false;
2903 }
2904
2905 // Set mGeometryInputPrimitiveType if exists
2906 if (layoutQualifier.primitiveType != EptUndefined)
2907 {
2908 if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier))
2909 {
2910 error(typeQualifier.line, "invalid primitive type for 'in' layout", "layout");
2911 return false;
2912 }
2913
2914 if (mGeometryShaderInputPrimitiveType == EptUndefined)
2915 {
2916 mGeometryShaderInputPrimitiveType = layoutQualifier.primitiveType;
Jiawei Shao8e4b3552017-08-30 14:20:58 +08002917 setGeometryShaderInputArraySize(
2918 GetGeometryShaderInputArraySize(mGeometryShaderInputPrimitiveType),
2919 typeQualifier.line);
Shaob5cc1192017-07-06 10:47:20 +08002920 }
2921 else if (mGeometryShaderInputPrimitiveType != layoutQualifier.primitiveType)
2922 {
2923 error(typeQualifier.line, "primitive doesn't match earlier input primitive declaration",
2924 "layout");
2925 return false;
2926 }
2927 }
2928
2929 // Set mGeometryInvocations if exists
2930 if (layoutQualifier.invocations > 0)
2931 {
2932 if (mGeometryShaderInvocations == 0)
2933 {
2934 mGeometryShaderInvocations = layoutQualifier.invocations;
2935 }
2936 else if (mGeometryShaderInvocations != layoutQualifier.invocations)
2937 {
2938 error(typeQualifier.line, "invocations contradicts to the earlier declaration",
2939 "layout");
2940 return false;
2941 }
2942 }
2943
2944 return true;
2945}
2946
2947bool TParseContext::parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier)
2948{
2949 ASSERT(typeQualifier.qualifier == EvqGeometryOut);
2950
2951 const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
2952
2953 if (layoutQualifier.invocations > 0)
2954 {
2955 error(typeQualifier.line,
2956 "invocations can only be declared in 'in' layout in a geometry shader", "layout");
2957 return false;
2958 }
2959
2960 // Set mGeometryOutputPrimitiveType if exists
2961 if (layoutQualifier.primitiveType != EptUndefined)
2962 {
2963 if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier))
2964 {
2965 error(typeQualifier.line, "invalid primitive type for 'out' layout", "layout");
2966 return false;
2967 }
2968
2969 if (mGeometryShaderOutputPrimitiveType == EptUndefined)
2970 {
2971 mGeometryShaderOutputPrimitiveType = layoutQualifier.primitiveType;
2972 }
2973 else if (mGeometryShaderOutputPrimitiveType != layoutQualifier.primitiveType)
2974 {
2975 error(typeQualifier.line,
2976 "primitive doesn't match earlier output primitive declaration", "layout");
2977 return false;
2978 }
2979 }
2980
2981 // Set mGeometryMaxVertices if exists
2982 if (layoutQualifier.maxVertices > -1)
2983 {
2984 if (mGeometryShaderMaxVertices == -1)
2985 {
2986 mGeometryShaderMaxVertices = layoutQualifier.maxVertices;
2987 }
2988 else if (mGeometryShaderMaxVertices != layoutQualifier.maxVertices)
2989 {
2990 error(typeQualifier.line, "max_vertices contradicts to the earlier declaration",
2991 "layout");
2992 return false;
2993 }
2994 }
2995
2996 return true;
2997}
2998
Martin Radev70866b82016-07-22 15:27:42 +03002999void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
Jamie Madilla295edf2013-06-06 11:56:48 -04003000{
Olli Etuaho77ba4082016-12-16 12:01:18 +00003001 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madilla295edf2013-06-06 11:56:48 -04003002 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04003003
Martin Radev70866b82016-07-22 15:27:42 +03003004 checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
3005 typeQualifier.line);
3006
Jamie Madillc2128ff2016-07-04 10:26:17 -04003007 // It should never be the case, but some strange parser errors can send us here.
3008 if (layoutQualifier.isEmpty())
3009 {
3010 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04003011 return;
3012 }
Jamie Madilla295edf2013-06-06 11:56:48 -04003013
Martin Radev802abe02016-08-04 17:48:32 +03003014 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04003015 {
Olli Etuaho43364892017-02-13 16:00:12 +00003016 error(typeQualifier.line, "invalid layout qualifier combination", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04003017 return;
3018 }
3019
Olli Etuahoa78092c2018-09-26 14:16:13 +03003020 checkIndexIsNotSpecified(typeQualifier.line, layoutQualifier.index);
3021
Olli Etuaho43364892017-02-13 16:00:12 +00003022 checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);
3023
3024 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev2cc85b32016-08-05 16:22:53 +03003025
3026 checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
3027
Andrei Volykhina5527072017-03-22 16:46:30 +03003028 checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv);
3029
jchen104cdac9e2017-05-08 11:01:20 +08003030 checkOffsetIsNotSpecified(typeQualifier.line, layoutQualifier.offset);
3031
Qin Jiajiaca68d982017-09-18 16:41:56 +08003032 checkStd430IsForShaderStorageBlock(typeQualifier.line, layoutQualifier.blockStorage,
3033 typeQualifier.qualifier);
3034
Martin Radev802abe02016-08-04 17:48:32 +03003035 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04003036 {
Martin Radev802abe02016-08-04 17:48:32 +03003037 if (mComputeShaderLocalSizeDeclared &&
3038 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
3039 {
3040 error(typeQualifier.line, "Work group size does not match the previous declaration",
3041 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03003042 return;
3043 }
Jamie Madilla295edf2013-06-06 11:56:48 -04003044
Martin Radev802abe02016-08-04 17:48:32 +03003045 if (mShaderVersion < 310)
3046 {
3047 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03003048 return;
3049 }
Jamie Madill099c0f32013-06-20 11:55:52 -04003050
Martin Radev4c4c8e72016-08-04 12:25:34 +03003051 if (!layoutQualifier.localSize.isAnyValueSet())
Martin Radev802abe02016-08-04 17:48:32 +03003052 {
3053 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03003054 return;
3055 }
3056
3057 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
Olli Etuahofbb1c792018-01-19 16:26:59 +02003058 symbolTable.findBuiltIn(ImmutableString("gl_MaxComputeWorkGroupSize"), mShaderVersion));
Martin Radev802abe02016-08-04 17:48:32 +03003059
3060 const TConstantUnion *maxComputeWorkGroupSizeData =
3061 maxComputeWorkGroupSize->getConstPointer();
3062
3063 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
3064 {
3065 if (layoutQualifier.localSize[i] != -1)
3066 {
3067 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
3068 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
3069 if (mComputeShaderLocalSize[i] < 1 ||
3070 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
3071 {
Jonah Ryan-Davisf563fdc2019-01-31 13:53:59 -05003072 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
Olli Etuaho4de340a2016-12-16 09:32:03 +00003073 reasonStream << "invalid value: Value must be at least 1 and no greater than "
3074 << maxComputeWorkGroupSizeValue;
3075 const std::string &reason = reasonStream.str();
Martin Radev802abe02016-08-04 17:48:32 +03003076
Olli Etuaho4de340a2016-12-16 09:32:03 +00003077 error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03003078 return;
3079 }
3080 }
3081 }
3082
3083 mComputeShaderLocalSizeDeclared = true;
3084 }
Shaob5cc1192017-07-06 10:47:20 +08003085 else if (typeQualifier.qualifier == EvqGeometryIn)
3086 {
3087 if (mShaderVersion < 310)
3088 {
3089 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
3090 return;
3091 }
3092
3093 if (!parseGeometryShaderInputLayoutQualifier(typeQualifier))
3094 {
3095 return;
3096 }
3097 }
3098 else if (typeQualifier.qualifier == EvqGeometryOut)
3099 {
3100 if (mShaderVersion < 310)
3101 {
3102 error(typeQualifier.line, "out type qualifier supported in GLSL ES 3.10 only",
3103 "layout");
3104 return;
3105 }
3106
3107 if (!parseGeometryShaderOutputLayoutQualifier(typeQualifier))
3108 {
3109 return;
3110 }
3111 }
Mingyu Huebab6702019-04-19 14:36:45 -07003112 else if (anyMultiviewExtensionAvailable() && typeQualifier.qualifier == EvqVertexIn)
Olli Etuaho09b04a22016-12-15 13:30:26 +00003113 {
3114 // This error is only specified in WebGL, but tightens unspecified behavior in the native
3115 // specification.
3116 if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
3117 {
3118 error(typeQualifier.line, "Number of views does not match the previous declaration",
3119 "layout");
3120 return;
3121 }
3122
3123 if (layoutQualifier.numViews == -1)
3124 {
3125 error(typeQualifier.line, "No num_views specified", "layout");
3126 return;
3127 }
3128
3129 if (layoutQualifier.numViews > mMaxNumViews)
3130 {
3131 error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
3132 "layout");
3133 return;
3134 }
3135
3136 mNumViews = layoutQualifier.numViews;
3137 }
Martin Radev802abe02016-08-04 17:48:32 +03003138 else
Jamie Madill1566ef72013-06-20 11:55:54 -04003139 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00003140 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03003141 {
Martin Radev802abe02016-08-04 17:48:32 +03003142 return;
3143 }
3144
Jiajia Qinbc585152017-06-23 15:42:17 +08003145 if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer)
Martin Radev802abe02016-08-04 17:48:32 +03003146 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003147 error(typeQualifier.line, "invalid qualifier: global layout can only be set for blocks",
Olli Etuaho4de340a2016-12-16 09:32:03 +00003148 getQualifierString(typeQualifier.qualifier));
Martin Radev802abe02016-08-04 17:48:32 +03003149 return;
3150 }
3151
3152 if (mShaderVersion < 300)
3153 {
3154 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
3155 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03003156 return;
3157 }
3158
Olli Etuaho09b04a22016-12-15 13:30:26 +00003159 checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003160
3161 if (layoutQualifier.matrixPacking != EmpUnspecified)
3162 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003163 if (typeQualifier.qualifier == EvqUniform)
3164 {
3165 mDefaultUniformMatrixPacking = layoutQualifier.matrixPacking;
3166 }
3167 else if (typeQualifier.qualifier == EvqBuffer)
3168 {
3169 mDefaultBufferMatrixPacking = layoutQualifier.matrixPacking;
3170 }
Martin Radev802abe02016-08-04 17:48:32 +03003171 }
3172
3173 if (layoutQualifier.blockStorage != EbsUnspecified)
3174 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003175 if (typeQualifier.qualifier == EvqUniform)
3176 {
3177 mDefaultUniformBlockStorage = layoutQualifier.blockStorage;
3178 }
3179 else if (typeQualifier.qualifier == EvqBuffer)
3180 {
3181 mDefaultBufferBlockStorage = layoutQualifier.blockStorage;
3182 }
Martin Radev802abe02016-08-04 17:48:32 +03003183 }
Jamie Madill1566ef72013-06-20 11:55:54 -04003184 }
Jamie Madilla295edf2013-06-06 11:56:48 -04003185}
3186
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003187TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
3188 const TFunction &function,
3189 const TSourceLoc &location,
3190 bool insertParametersToSymbolTable)
3191{
Olli Etuahobed35d72017-12-20 16:36:26 +02003192 checkIsNotReserved(location, function.name());
Olli Etuahod7cd4ae2017-07-06 15:52:49 +03003193
Olli Etuahobeb6dc72017-12-14 16:03:03 +02003194 TIntermFunctionPrototype *prototype = new TIntermFunctionPrototype(&function);
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003195 prototype->setLine(location);
3196
3197 for (size_t i = 0; i < function.getParamCount(); i++)
3198 {
Olli Etuahod4bd9632018-03-08 16:32:44 +02003199 const TVariable *param = function.getParam(i);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003200
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003201 // If the parameter has no name, it's not an error, just don't add it to symbol table (could
3202 // be used for unused args).
Olli Etuahod4bd9632018-03-08 16:32:44 +02003203 if (param->symbolType() != SymbolType::Empty)
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003204 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003205 if (insertParametersToSymbolTable)
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003206 {
Olli Etuahod4bd9632018-03-08 16:32:44 +02003207 if (!symbolTable.declare(const_cast<TVariable *>(param)))
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003208 {
Olli Etuahod4bd9632018-03-08 16:32:44 +02003209 error(location, "redefinition", param->name());
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03003210 }
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003211 }
Olli Etuaho55bde912017-10-25 13:41:13 +03003212 // Unsized type of a named parameter should have already been checked and sanitized.
Olli Etuahod4bd9632018-03-08 16:32:44 +02003213 ASSERT(!param->getType().isUnsizedArray());
Olli Etuaho55bde912017-10-25 13:41:13 +03003214 }
3215 else
3216 {
Olli Etuahod4bd9632018-03-08 16:32:44 +02003217 if (param->getType().isUnsizedArray())
Olli Etuaho55bde912017-10-25 13:41:13 +03003218 {
3219 error(location, "function parameter array must be sized at compile time", "[]");
3220 // We don't need to size the arrays since the parameter is unnamed and hence
3221 // inaccessible.
3222 }
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003223 }
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003224 }
3225 return prototype;
3226}
3227
Olli Etuaho16c745a2017-01-16 17:02:27 +00003228TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
3229 const TFunction &parsedFunction,
3230 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003231{
Olli Etuaho476197f2016-10-11 13:59:08 +01003232 // Note: function found from the symbol table could be the same as parsedFunction if this is the
3233 // first declaration. Either way the instance in the symbol table is used to track whether the
3234 // function is declared multiple times.
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003235 bool hadPrototypeDeclaration = false;
Olli Etuaho7c8567a2018-02-20 15:44:07 +02003236 const TFunction *function = symbolTable.markFunctionHasPrototypeDeclaration(
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003237 parsedFunction.getMangledName(), &hadPrototypeDeclaration);
3238
3239 if (hadPrototypeDeclaration && mShaderVersion == 100)
Olli Etuaho5d653182016-01-04 14:43:28 +02003240 {
3241 // ESSL 1.00.17 section 4.2.7.
3242 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
3243 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02003244 }
Olli Etuaho5d653182016-01-04 14:43:28 +02003245
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003246 TIntermFunctionPrototype *prototype =
3247 createPrototypeNodeFromFunction(*function, location, false);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003248
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003249 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02003250
3251 if (!symbolTable.atGlobalLevel())
3252 {
3253 // ESSL 3.00.4 section 4.2.4.
3254 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02003255 }
3256
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003257 return prototype;
3258}
3259
Olli Etuaho336b1472016-10-05 16:37:55 +01003260TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003261 TIntermFunctionPrototype *functionPrototype,
Olli Etuaho336b1472016-10-05 16:37:55 +01003262 TIntermBlock *functionBody,
3263 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003264{
Olli Etuahof51fdd22016-10-03 10:03:40 +01003265 // Check that non-void functions have at least one return statement.
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003266 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
3267 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02003268 error(location,
3269 "function does not return a value:", functionPrototype->getFunction()->name());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003270 }
3271
Olli Etuahof51fdd22016-10-03 10:03:40 +01003272 if (functionBody == nullptr)
3273 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01003274 functionBody = new TIntermBlock();
Olli Etuahof51fdd22016-10-03 10:03:40 +01003275 functionBody->setLine(location);
3276 }
Olli Etuaho336b1472016-10-05 16:37:55 +01003277 TIntermFunctionDefinition *functionNode =
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003278 new TIntermFunctionDefinition(functionPrototype, functionBody);
Olli Etuaho336b1472016-10-05 16:37:55 +01003279 functionNode->setLine(location);
Olli Etuahof51fdd22016-10-03 10:03:40 +01003280
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003281 symbolTable.pop();
Olli Etuahof51fdd22016-10-03 10:03:40 +01003282 return functionNode;
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003283}
3284
Olli Etuaho476197f2016-10-11 13:59:08 +01003285void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003286 const TFunction *function,
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003287 TIntermFunctionPrototype **prototypeOut)
Jamie Madill185fb402015-06-12 15:48:48 -04003288{
Olli Etuaho476197f2016-10-11 13:59:08 +01003289 ASSERT(function);
Jamie Madill185fb402015-06-12 15:48:48 -04003290
Olli Etuaho7c8567a2018-02-20 15:44:07 +02003291 bool wasDefined = false;
3292 function = symbolTable.setFunctionParameterNamesFromDefinition(function, &wasDefined);
3293 if (wasDefined)
Jamie Madill185fb402015-06-12 15:48:48 -04003294 {
Olli Etuaho7c8567a2018-02-20 15:44:07 +02003295 error(location, "function already has a body", function->name());
Jamie Madill185fb402015-06-12 15:48:48 -04003296 }
Jamie Madill185fb402015-06-12 15:48:48 -04003297
Olli Etuaho8ad9e752017-01-16 19:55:20 +00003298 // Remember the return type for later checking for return statements.
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003299 mCurrentFunctionType = &(function->getReturnType());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02003300 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04003301
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003302 *prototypeOut = createPrototypeNodeFromFunction(*function, location, true);
Jamie Madill185fb402015-06-12 15:48:48 -04003303 setLoopNestingLevel(0);
3304}
3305
Jamie Madillb98c3a82015-07-23 14:26:04 -04003306TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04003307{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00003308 //
Olli Etuaho5d653182016-01-04 14:43:28 +02003309 // We don't know at this point whether this is a function definition or a prototype.
3310 // The definition production code will check for redefinitions.
3311 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00003312 //
Olli Etuahoc4a96d62015-07-23 17:37:39 +05303313
Olli Etuahod80f2942017-11-06 12:44:45 +02003314 for (size_t i = 0u; i < function->getParamCount(); ++i)
3315 {
Olli Etuahod4bd9632018-03-08 16:32:44 +02003316 const TVariable *param = function->getParam(i);
3317 if (param->getType().isStructSpecifier())
Olli Etuahod80f2942017-11-06 12:44:45 +02003318 {
3319 // ESSL 3.00.6 section 12.10.
3320 error(location, "Function parameter type cannot be a structure definition",
Olli Etuahofbb1c792018-01-19 16:26:59 +02003321 function->name());
Olli Etuahod80f2942017-11-06 12:44:45 +02003322 }
3323 }
3324
Olli Etuaho7c8567a2018-02-20 15:44:07 +02003325 if (getShaderVersion() >= 300)
Olli Etuahoc4a96d62015-07-23 17:37:39 +05303326 {
Olli Etuaho7c8567a2018-02-20 15:44:07 +02003327 const UnmangledBuiltIn *builtIn =
3328 symbolTable.getUnmangledBuiltInForShaderVersion(function->name(), getShaderVersion());
3329 if (builtIn &&
3330 (builtIn->extension == TExtension::UNDEFINED || isExtensionEnabled(builtIn->extension)))
3331 {
3332 // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as
3333 // functions. Therefore overloading or redefining builtin functions is an error.
3334 error(location, "Name of a built-in function cannot be redeclared as function",
3335 function->name());
3336 }
Olli Etuahoc4a96d62015-07-23 17:37:39 +05303337 }
Olli Etuaho7c8567a2018-02-20 15:44:07 +02003338 else
3339 {
3340 // ESSL 1.00.17 section 4.2.6: built-ins can be overloaded but not redefined. We assume that
3341 // this applies to redeclarations as well.
3342 const TSymbol *builtIn =
3343 symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
3344 if (builtIn)
3345 {
3346 error(location, "built-in functions cannot be redefined", function->name());
3347 }
3348 }
3349
3350 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
3351 // here.
3352 const TFunction *prevDec =
3353 static_cast<const TFunction *>(symbolTable.findGlobal(function->getMangledName()));
3354 if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04003355 {
3356 if (prevDec->getReturnType() != function->getReturnType())
3357 {
Olli Etuaho476197f2016-10-11 13:59:08 +01003358 error(location, "function must have the same return type in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04003359 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04003360 }
3361 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
3362 {
Olli Etuahod4bd9632018-03-08 16:32:44 +02003363 if (prevDec->getParam(i)->getType().getQualifier() !=
3364 function->getParam(i)->getType().getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04003365 {
Olli Etuaho476197f2016-10-11 13:59:08 +01003366 error(location,
3367 "function must have the same parameter qualifiers in all of its declarations",
Olli Etuahod4bd9632018-03-08 16:32:44 +02003368 function->getParam(i)->getType().getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04003369 }
3370 }
3371 }
3372
Jamie Madill185fb402015-06-12 15:48:48 -04003373 // Check for previously declared variables using the same name.
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003374 const TSymbol *prevSym = symbolTable.find(function->name(), getShaderVersion());
3375 bool insertUnmangledName = true;
Jamie Madill185fb402015-06-12 15:48:48 -04003376 if (prevSym)
3377 {
3378 if (!prevSym->isFunction())
3379 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02003380 error(location, "redefinition of a function", function->name());
Jamie Madill185fb402015-06-12 15:48:48 -04003381 }
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003382 insertUnmangledName = false;
Jamie Madill185fb402015-06-12 15:48:48 -04003383 }
Olli Etuahodd21ecf2018-01-10 12:42:09 +02003384 // Parsing is at the inner scope level of the function's arguments and body statement at this
3385 // point, but declareUserDefinedFunction takes care of declaring the function at the global
3386 // scope.
3387 symbolTable.declareUserDefinedFunction(function, insertUnmangledName);
Jamie Madill185fb402015-06-12 15:48:48 -04003388
Olli Etuaho78d13742017-01-18 13:06:10 +00003389 // Raise error message if main function takes any parameters or return anything other than void
Olli Etuahofbb1c792018-01-19 16:26:59 +02003390 if (function->isMain())
Olli Etuaho78d13742017-01-18 13:06:10 +00003391 {
3392 if (function->getParamCount() > 0)
3393 {
3394 error(location, "function cannot take any parameter(s)", "main");
3395 }
3396 if (function->getReturnType().getBasicType() != EbtVoid)
3397 {
3398 error(location, "main function cannot return a value",
3399 function->getReturnType().getBasicString());
3400 }
3401 }
3402
Jamie Madill185fb402015-06-12 15:48:48 -04003403 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04003404 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
3405 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04003406 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
3407 //
3408 return function;
3409}
3410
Olli Etuaho9de84a52016-06-14 17:36:01 +03003411TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
Olli Etuahofbb1c792018-01-19 16:26:59 +02003412 const ImmutableString &name,
Olli Etuaho9de84a52016-06-14 17:36:01 +03003413 const TSourceLoc &location)
3414{
3415 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
3416 {
3417 error(location, "no qualifiers allowed for function return",
3418 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03003419 }
3420 if (!type.layoutQualifier.isEmpty())
3421 {
3422 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03003423 }
jchen10cc2a10e2017-05-03 14:05:12 +08003424 // make sure an opaque type is not involved as well...
3425 std::string reason(getBasicString(type.getBasicType()));
3426 reason += "s can't be function return values";
3427 checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03003428 if (mShaderVersion < 300)
3429 {
3430 // Array return values are forbidden, but there's also no valid syntax for declaring array
3431 // return values in ESSL 1.00.
Olli Etuaho7881cfd2017-08-23 18:00:21 +03003432 ASSERT(!type.isArray() || mDiagnostics->numErrors() > 0);
Olli Etuahoe29324f2016-06-15 10:58:03 +03003433
3434 if (type.isStructureContainingArrays())
3435 {
3436 // ESSL 1.00.17 section 6.1 Function Definitions
Olli Etuaho72e35892018-06-20 11:43:08 +03003437 TInfoSinkBase typeString;
3438 typeString << TType(type);
Olli Etuahoe29324f2016-06-15 10:58:03 +03003439 error(location, "structures containing arrays can't be function return values",
Olli Etuaho72e35892018-06-20 11:43:08 +03003440 typeString.c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03003441 }
3442 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03003443
3444 // Add the function as a prototype after parsing it (we do not support recursion)
Olli Etuaho029e8ca2018-02-16 14:06:49 +02003445 return new TFunction(&symbolTable, name, SymbolType::UserDefined, new TType(type), false);
Olli Etuaho9de84a52016-06-14 17:36:01 +03003446}
3447
Olli Etuaho697bf652018-02-16 11:50:54 +02003448TFunctionLookup *TParseContext::addNonConstructorFunc(const ImmutableString &name,
3449 const TSymbol *symbol)
Olli Etuahocce89652017-06-19 16:04:09 +03003450{
Olli Etuaho697bf652018-02-16 11:50:54 +02003451 return TFunctionLookup::CreateFunctionCall(name, symbol);
Olli Etuahocce89652017-06-19 16:04:09 +03003452}
3453
Olli Etuaho95ed1942018-02-01 14:01:19 +02003454TFunctionLookup *TParseContext::addConstructorFunc(const TPublicType &publicType)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00003455{
Olli Etuaho7881cfd2017-08-23 18:00:21 +03003456 if (mShaderVersion < 300 && publicType.isArray())
Olli Etuahocce89652017-06-19 16:04:09 +03003457 {
3458 error(publicType.getLine(), "array constructor supported in GLSL ES 3.00 and above only",
3459 "[]");
3460 }
Martin Radev4a9cd802016-09-01 16:51:51 +03003461 if (publicType.isStructSpecifier())
Olli Etuahobd163f62015-11-13 12:15:38 +02003462 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003463 error(publicType.getLine(), "constructor can't be a structure definition",
3464 getBasicString(publicType.getBasicType()));
Olli Etuahobd163f62015-11-13 12:15:38 +02003465 }
3466
Olli Etuahoa7ecec32017-05-08 17:43:55 +03003467 TType *type = new TType(publicType);
3468 if (!type->canBeConstructed())
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00003469 {
Olli Etuahoa7ecec32017-05-08 17:43:55 +03003470 error(publicType.getLine(), "cannot construct this type",
3471 getBasicString(publicType.getBasicType()));
3472 type->setBasicType(EbtFloat);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00003473 }
Olli Etuaho95ed1942018-02-01 14:01:19 +02003474 return TFunctionLookup::CreateConstructor(type);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00003475}
3476
Olli Etuaho55bde912017-10-25 13:41:13 +03003477void TParseContext::checkIsNotUnsizedArray(const TSourceLoc &line,
3478 const char *errorMessage,
Olli Etuahofbb1c792018-01-19 16:26:59 +02003479 const ImmutableString &token,
Olli Etuaho55bde912017-10-25 13:41:13 +03003480 TType *arrayType)
3481{
3482 if (arrayType->isUnsizedArray())
3483 {
3484 error(line, errorMessage, token);
Kai Ninomiya57ea5332017-11-22 14:04:48 -08003485 arrayType->sizeUnsizedArrays(nullptr);
Olli Etuaho55bde912017-10-25 13:41:13 +03003486 }
3487}
3488
3489TParameter TParseContext::parseParameterDeclarator(TType *type,
Olli Etuahofbb1c792018-01-19 16:26:59 +02003490 const ImmutableString &name,
Olli Etuahocce89652017-06-19 16:04:09 +03003491 const TSourceLoc &nameLoc)
3492{
Olli Etuaho55bde912017-10-25 13:41:13 +03003493 ASSERT(type);
Olli Etuahofbb1c792018-01-19 16:26:59 +02003494 checkIsNotUnsizedArray(nameLoc, "function parameter array must specify a size", name, type);
Olli Etuaho55bde912017-10-25 13:41:13 +03003495 if (type->getBasicType() == EbtVoid)
Olli Etuahocce89652017-06-19 16:04:09 +03003496 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02003497 error(nameLoc, "illegal use of type 'void'", name);
Olli Etuahocce89652017-06-19 16:04:09 +03003498 }
Olli Etuahofbb1c792018-01-19 16:26:59 +02003499 checkIsNotReserved(nameLoc, name);
3500 TParameter param = {name.data(), type};
Olli Etuahocce89652017-06-19 16:04:09 +03003501 return param;
3502}
3503
Olli Etuaho55bde912017-10-25 13:41:13 +03003504TParameter TParseContext::parseParameterDeclarator(const TPublicType &publicType,
Olli Etuahofbb1c792018-01-19 16:26:59 +02003505 const ImmutableString &name,
Olli Etuaho55bde912017-10-25 13:41:13 +03003506 const TSourceLoc &nameLoc)
Olli Etuahocce89652017-06-19 16:04:09 +03003507{
Olli Etuaho55bde912017-10-25 13:41:13 +03003508 TType *type = new TType(publicType);
3509 return parseParameterDeclarator(type, name, nameLoc);
3510}
3511
Olli Etuahofbb1c792018-01-19 16:26:59 +02003512TParameter TParseContext::parseParameterArrayDeclarator(const ImmutableString &name,
Olli Etuaho55bde912017-10-25 13:41:13 +03003513 const TSourceLoc &nameLoc,
Olli Etuaho7881cfd2017-08-23 18:00:21 +03003514 const TVector<unsigned int> &arraySizes,
Olli Etuaho55bde912017-10-25 13:41:13 +03003515 const TSourceLoc &arrayLoc,
3516 TPublicType *elementType)
3517{
3518 checkArrayElementIsNotArray(arrayLoc, *elementType);
3519 TType *arrayType = new TType(*elementType);
Olli Etuaho7881cfd2017-08-23 18:00:21 +03003520 arrayType->makeArrays(arraySizes);
Olli Etuaho55bde912017-10-25 13:41:13 +03003521 return parseParameterDeclarator(arrayType, name, nameLoc);
Olli Etuahocce89652017-06-19 16:04:09 +03003522}
3523
Olli Etuaho95ed1942018-02-01 14:01:19 +02003524bool TParseContext::checkUnsizedArrayConstructorArgumentDimensionality(
3525 const TIntermSequence &arguments,
3526 TType type,
3527 const TSourceLoc &line)
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003528{
Olli Etuaho95ed1942018-02-01 14:01:19 +02003529 if (arguments.empty())
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003530 {
3531 error(line, "implicitly sized array constructor must have at least one argument", "[]");
3532 return false;
3533 }
Olli Etuaho95ed1942018-02-01 14:01:19 +02003534 for (TIntermNode *arg : arguments)
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003535 {
Olli Etuaho95ed1942018-02-01 14:01:19 +02003536 const TIntermTyped *element = arg->getAsTyped();
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003537 ASSERT(element);
Kai Ninomiya57ea5332017-11-22 14:04:48 -08003538 size_t dimensionalityFromElement = element->getType().getNumArraySizes() + 1u;
3539 if (dimensionalityFromElement > type.getNumArraySizes())
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003540 {
3541 error(line, "constructing from a non-dereferenced array", "constructor");
3542 return false;
3543 }
Kai Ninomiya57ea5332017-11-22 14:04:48 -08003544 else if (dimensionalityFromElement < type.getNumArraySizes())
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003545 {
3546 if (dimensionalityFromElement == 1u)
3547 {
3548 error(line, "implicitly sized array of arrays constructor argument is not an array",
3549 "constructor");
3550 }
3551 else
3552 {
3553 error(line,
3554 "implicitly sized array of arrays constructor argument dimensionality is too "
3555 "low",
3556 "constructor");
3557 }
3558 return false;
3559 }
3560 }
3561 return true;
3562}
3563
Jamie Madillb98c3a82015-07-23 14:26:04 -04003564// This function is used to test for the correctness of the parameters passed to various constructor
3565// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003566//
Olli Etuaho856c4972016-08-08 11:38:39 +03003567// 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 +00003568//
Olli Etuaho95ed1942018-02-01 14:01:19 +02003569TIntermTyped *TParseContext::addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003570{
Olli Etuaho95ed1942018-02-01 14:01:19 +02003571 TType type = fnCall->constructorType();
3572 TIntermSequence &arguments = fnCall->arguments();
Olli Etuaho856c4972016-08-08 11:38:39 +03003573 if (type.isUnsizedArray())
3574 {
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003575 if (!checkUnsizedArrayConstructorArgumentDimensionality(arguments, type, line))
Olli Etuahobbe9fb52016-11-03 17:16:05 +00003576 {
Kai Ninomiya57ea5332017-11-22 14:04:48 -08003577 type.sizeUnsizedArrays(nullptr);
Olli Etuaho3ec75682017-07-05 17:02:55 +03003578 return CreateZeroNode(type);
Olli Etuahobbe9fb52016-11-03 17:16:05 +00003579 }
Olli Etuaho95ed1942018-02-01 14:01:19 +02003580 TIntermTyped *firstElement = arguments.at(0)->getAsTyped();
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003581 ASSERT(firstElement);
Olli Etuaho9cd71632017-10-26 14:43:20 +03003582 if (type.getOutermostArraySize() == 0u)
3583 {
Olli Etuaho95ed1942018-02-01 14:01:19 +02003584 type.sizeOutermostUnsizedArray(static_cast<unsigned int>(arguments.size()));
Olli Etuaho9cd71632017-10-26 14:43:20 +03003585 }
Kai Ninomiya57ea5332017-11-22 14:04:48 -08003586 for (size_t i = 0; i < firstElement->getType().getNumArraySizes(); ++i)
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003587 {
Kai Ninomiya57ea5332017-11-22 14:04:48 -08003588 if ((*type.getArraySizes())[i] == 0u)
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003589 {
Kai Ninomiya57ea5332017-11-22 14:04:48 -08003590 type.setArraySize(i, (*firstElement->getType().getArraySizes())[i]);
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003591 }
3592 }
3593 ASSERT(!type.isUnsizedArray());
Olli Etuaho856c4972016-08-08 11:38:39 +03003594 }
Olli Etuaho856c4972016-08-08 11:38:39 +03003595
Olli Etuahoa7ecec32017-05-08 17:43:55 +03003596 if (!checkConstructorArguments(line, arguments, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03003597 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03003598 return CreateZeroNode(type);
Olli Etuaho856c4972016-08-08 11:38:39 +03003599 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003600
Olli Etuaho95ed1942018-02-01 14:01:19 +02003601 TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, &arguments);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08003602 constructorNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003603
Olli Etuaho765924f2018-01-04 12:48:36 +02003604 return constructorNode->fold(mDiagnostics);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003605}
3606
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003607//
3608// Interface/uniform blocks
Jiawei Shaobd924af2017-11-16 15:28:04 +08003609// TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003610//
Olli Etuaho13389b62016-10-16 11:48:18 +01003611TIntermDeclaration *TParseContext::addInterfaceBlock(
Martin Radev70866b82016-07-22 15:27:42 +03003612 const TTypeQualifierBuilder &typeQualifierBuilder,
3613 const TSourceLoc &nameLine,
Olli Etuahofbb1c792018-01-19 16:26:59 +02003614 const ImmutableString &blockName,
Martin Radev70866b82016-07-22 15:27:42 +03003615 TFieldList *fieldList,
Olli Etuahofbb1c792018-01-19 16:26:59 +02003616 const ImmutableString &instanceName,
Martin Radev70866b82016-07-22 15:27:42 +03003617 const TSourceLoc &instanceLine,
3618 TIntermTyped *arrayIndex,
3619 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003620{
Olli Etuaho856c4972016-08-08 11:38:39 +03003621 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003622
Olli Etuaho77ba4082016-12-16 12:01:18 +00003623 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03003624
Jiajia Qinbc585152017-06-23 15:42:17 +08003625 if (mShaderVersion < 310 && typeQualifier.qualifier != EvqUniform)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003626 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003627 error(typeQualifier.line,
3628 "invalid qualifier: interface blocks must be uniform in version lower than GLSL ES "
3629 "3.10",
3630 getQualifierString(typeQualifier.qualifier));
3631 }
3632 else if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer)
3633 {
3634 error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform or buffer",
Olli Etuaho4de340a2016-12-16 09:32:03 +00003635 getQualifierString(typeQualifier.qualifier));
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003636 }
3637
Martin Radev70866b82016-07-22 15:27:42 +03003638 if (typeQualifier.invariant)
3639 {
3640 error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
3641 }
3642
Jiajia Qinbc585152017-06-23 15:42:17 +08003643 if (typeQualifier.qualifier != EvqBuffer)
3644 {
3645 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
3646 }
Olli Etuaho43364892017-02-13 16:00:12 +00003647
jchen10af713a22017-04-19 09:10:56 +08003648 // add array index
3649 unsigned int arraySize = 0;
3650 if (arrayIndex != nullptr)
3651 {
3652 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
3653 }
3654
Olli Etuahoa78092c2018-09-26 14:16:13 +03003655 checkIndexIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.index);
3656
jchen10af713a22017-04-19 09:10:56 +08003657 if (mShaderVersion < 310)
3658 {
3659 checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
3660 }
3661 else
3662 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003663 checkBlockBindingIsValid(typeQualifier.line, typeQualifier.qualifier,
3664 typeQualifier.layoutQualifier.binding, arraySize);
jchen10af713a22017-04-19 09:10:56 +08003665 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003666
Andrei Volykhina5527072017-03-22 16:46:30 +03003667 checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
3668
Jamie Madill099c0f32013-06-20 11:55:52 -04003669 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03003670 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Qin Jiajiaca68d982017-09-18 16:41:56 +08003671 checkStd430IsForShaderStorageBlock(typeQualifier.line, blockLayoutQualifier.blockStorage,
3672 typeQualifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003673
Jamie Madill099c0f32013-06-20 11:55:52 -04003674 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
3675 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003676 if (typeQualifier.qualifier == EvqUniform)
3677 {
3678 blockLayoutQualifier.matrixPacking = mDefaultUniformMatrixPacking;
3679 }
3680 else if (typeQualifier.qualifier == EvqBuffer)
3681 {
3682 blockLayoutQualifier.matrixPacking = mDefaultBufferMatrixPacking;
3683 }
Jamie Madill099c0f32013-06-20 11:55:52 -04003684 }
3685
Jamie Madill1566ef72013-06-20 11:55:54 -04003686 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
3687 {
Jiajia Qinbc585152017-06-23 15:42:17 +08003688 if (typeQualifier.qualifier == EvqUniform)
3689 {
3690 blockLayoutQualifier.blockStorage = mDefaultUniformBlockStorage;
3691 }
3692 else if (typeQualifier.qualifier == EvqBuffer)
3693 {
3694 blockLayoutQualifier.blockStorage = mDefaultBufferBlockStorage;
3695 }
Jamie Madill1566ef72013-06-20 11:55:54 -04003696 }
3697
Olli Etuaho856c4972016-08-08 11:38:39 +03003698 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003699
Martin Radev2cc85b32016-08-05 16:22:53 +03003700 checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
3701
Jamie Madill98493dd2013-07-08 14:39:03 -04003702 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05303703 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
3704 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003705 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05303706 TType *fieldType = field->type();
jchen10cc2a10e2017-05-03 14:05:12 +08003707 if (IsOpaqueType(fieldType->getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +05303708 {
jchen10cc2a10e2017-05-03 14:05:12 +08003709 std::string reason("unsupported type - ");
3710 reason += fieldType->getBasicString();
3711 reason += " types are not allowed in interface blocks";
3712 error(field->line(), reason.c_str(), fieldType->getBasicString());
Martin Radev2cc85b32016-08-05 16:22:53 +03003713 }
3714
Jamie Madill98493dd2013-07-08 14:39:03 -04003715 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003716 switch (qualifier)
3717 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003718 case EvqGlobal:
Jiajia Qinbc585152017-06-23 15:42:17 +08003719 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003720 case EvqUniform:
Jiajia Qinbc585152017-06-23 15:42:17 +08003721 if (typeQualifier.qualifier == EvqBuffer)
3722 {
3723 error(field->line(), "invalid qualifier on shader storage block member",
3724 getQualifierString(qualifier));
3725 }
3726 break;
3727 case EvqBuffer:
3728 if (typeQualifier.qualifier == EvqUniform)
3729 {
3730 error(field->line(), "invalid qualifier on uniform block member",
3731 getQualifierString(qualifier));
3732 }
Jamie Madillb98c3a82015-07-23 14:26:04 -04003733 break;
3734 default:
3735 error(field->line(), "invalid qualifier on interface block member",
3736 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003737 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003738 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003739
Martin Radev70866b82016-07-22 15:27:42 +03003740 if (fieldType->isInvariant())
3741 {
3742 error(field->line(), "invalid qualifier on interface block member", "invariant");
3743 }
3744
Jamie Madilla5efff92013-06-06 11:56:47 -04003745 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04003746 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03003747 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Olli Etuahoa78092c2018-09-26 14:16:13 +03003748 checkIndexIsNotSpecified(field->line(), fieldLayoutQualifier.index);
jchen10af713a22017-04-19 09:10:56 +08003749 checkBindingIsNotSpecified(field->line(), fieldLayoutQualifier.binding);
Jamie Madill099c0f32013-06-20 11:55:52 -04003750
Jamie Madill98493dd2013-07-08 14:39:03 -04003751 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04003752 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003753 error(field->line(), "invalid layout qualifier: cannot be used here",
3754 getBlockStorageString(fieldLayoutQualifier.blockStorage));
Jamie Madill1566ef72013-06-20 11:55:54 -04003755 }
3756
Jamie Madill98493dd2013-07-08 14:39:03 -04003757 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04003758 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003759 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04003760 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03003761 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04003762 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003763 warning(field->line(),
3764 "extraneous layout qualifier: only has an effect on matrix types",
3765 getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
Jamie Madill099c0f32013-06-20 11:55:52 -04003766 }
3767
Jamie Madill98493dd2013-07-08 14:39:03 -04003768 fieldType->setLayoutQualifier(fieldLayoutQualifier);
Jiajia Qinbc585152017-06-23 15:42:17 +08003769
Olli Etuahoebee5b32017-11-23 12:56:32 +02003770 if (mShaderVersion < 310 || memberIndex != fieldList->size() - 1u ||
3771 typeQualifier.qualifier != EvqBuffer)
3772 {
3773 // ESSL 3.10 spec section 4.1.9 allows for runtime-sized arrays.
3774 checkIsNotUnsizedArray(field->line(),
3775 "array members of interface blocks must specify a size",
Olli Etuahofbb1c792018-01-19 16:26:59 +02003776 field->name(), field->type());
Olli Etuahoebee5b32017-11-23 12:56:32 +02003777 }
3778
Jiajia Qinbc585152017-06-23 15:42:17 +08003779 if (typeQualifier.qualifier == EvqBuffer)
3780 {
3781 // set memory qualifiers
3782 // GLSL ES 3.10 session 4.9 [Memory Access Qualifiers]. When a block declaration is
3783 // qualified with a memory qualifier, it is as if all of its members were declared with
3784 // the same memory qualifier.
3785 const TMemoryQualifier &blockMemoryQualifier = typeQualifier.memoryQualifier;
3786 TMemoryQualifier fieldMemoryQualifier = fieldType->getMemoryQualifier();
3787 fieldMemoryQualifier.readonly |= blockMemoryQualifier.readonly;
3788 fieldMemoryQualifier.writeonly |= blockMemoryQualifier.writeonly;
3789 fieldMemoryQualifier.coherent |= blockMemoryQualifier.coherent;
3790 fieldMemoryQualifier.restrictQualifier |= blockMemoryQualifier.restrictQualifier;
3791 fieldMemoryQualifier.volatileQualifier |= blockMemoryQualifier.volatileQualifier;
3792 // TODO(jiajia.qin@intel.com): Decide whether if readonly and writeonly buffer variable
3793 // is legal. See bug https://github.com/KhronosGroup/OpenGL-API/issues/7
3794 fieldType->setMemoryQualifier(fieldMemoryQualifier);
3795 }
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003796 }
3797
Olli Etuaho9d4d7f02017-12-07 17:11:41 +01003798 TInterfaceBlock *interfaceBlock = new TInterfaceBlock(
Olli Etuahofbb1c792018-01-19 16:26:59 +02003799 &symbolTable, blockName, fieldList, blockLayoutQualifier, SymbolType::UserDefined);
Olli Etuaho437664b2018-02-28 15:38:14 +02003800 if (!symbolTable.declare(interfaceBlock))
Olli Etuaho378c3a52017-12-04 11:32:13 +02003801 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02003802 error(nameLine, "redefinition of an interface block name", blockName);
Olli Etuaho378c3a52017-12-04 11:32:13 +02003803 }
3804
Olli Etuahob60d30f2018-01-16 12:31:06 +02003805 TType *interfaceBlockType =
3806 new TType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier);
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003807 if (arrayIndex != nullptr)
3808 {
Olli Etuahob60d30f2018-01-16 12:31:06 +02003809 interfaceBlockType->makeArray(arraySize);
Olli Etuaho96f6adf2017-08-16 11:18:54 +03003810 }
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003811
Olli Etuaho195be942017-12-04 23:40:14 +02003812 // The instance variable gets created to refer to the interface block type from the AST
Olli Etuahoae4dbf32017-12-08 20:49:00 +01003813 // regardless of if there's an instance name. It's created as an empty symbol if there is no
3814 // instance name.
Olli Etuaho195be942017-12-04 23:40:14 +02003815 TVariable *instanceVariable =
Olli Etuahoae4dbf32017-12-08 20:49:00 +01003816 new TVariable(&symbolTable, instanceName, interfaceBlockType,
Olli Etuahofbb1c792018-01-19 16:26:59 +02003817 instanceName.empty() ? SymbolType::Empty : SymbolType::UserDefined);
Olli Etuaho195be942017-12-04 23:40:14 +02003818
Olli Etuahoae4dbf32017-12-08 20:49:00 +01003819 if (instanceVariable->symbolType() == SymbolType::Empty)
Olli Etuaho195be942017-12-04 23:40:14 +02003820 {
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003821 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04003822 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
3823 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003824 TField *field = (*fieldList)[memberIndex];
Olli Etuahob60d30f2018-01-16 12:31:06 +02003825 TType *fieldType = new TType(*field->type());
Jamie Madill98493dd2013-07-08 14:39:03 -04003826
3827 // set parent pointer of the field variable
3828 fieldType->setInterfaceBlock(interfaceBlock);
3829
Olli Etuahob60d30f2018-01-16 12:31:06 +02003830 fieldType->setQualifier(typeQualifier.qualifier);
3831
Olli Etuaho195be942017-12-04 23:40:14 +02003832 TVariable *fieldVariable =
Olli Etuahofbb1c792018-01-19 16:26:59 +02003833 new TVariable(&symbolTable, field->name(), fieldType, SymbolType::UserDefined);
Olli Etuaho437664b2018-02-28 15:38:14 +02003834 if (!symbolTable.declare(fieldVariable))
Arun Patole7e7e68d2015-05-22 12:02:25 +05303835 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003836 error(field->line(), "redefinition of an interface block member name",
Olli Etuahofbb1c792018-01-19 16:26:59 +02003837 field->name());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003838 }
3839 }
3840 }
3841 else
3842 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02003843 checkIsNotReserved(instanceLine, instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03003844
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003845 // add a symbol for this interface block
Olli Etuaho437664b2018-02-28 15:38:14 +02003846 if (!symbolTable.declare(instanceVariable))
Arun Patole7e7e68d2015-05-22 12:02:25 +05303847 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02003848 error(instanceLine, "redefinition of an interface block instance name", instanceName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003849 }
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003850 }
3851
Olli Etuaho195be942017-12-04 23:40:14 +02003852 TIntermSymbol *blockSymbol = new TIntermSymbol(instanceVariable);
3853 blockSymbol->setLine(typeQualifier.line);
3854 TIntermDeclaration *declaration = new TIntermDeclaration();
3855 declaration->appendDeclarator(blockSymbol);
3856 declaration->setLine(nameLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04003857
3858 exitStructDeclaration();
Olli Etuaho13389b62016-10-16 11:48:18 +01003859 return declaration;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003860}
3861
Olli Etuahofbb1c792018-01-19 16:26:59 +02003862void TParseContext::enterStructDeclaration(const TSourceLoc &line,
3863 const ImmutableString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00003864{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003865 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003866
3867 // Embedded structure definitions are not supported per GLSL ES spec.
Olli Etuaho4de340a2016-12-16 09:32:03 +00003868 // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
Arun Patole7e7e68d2015-05-22 12:02:25 +05303869 if (mStructNestingLevel > 1)
3870 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003871 error(line, "Embedded struct definitions are not allowed", "struct");
kbr@chromium.org476541f2011-10-27 21:14:51 +00003872 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00003873}
3874
3875void TParseContext::exitStructDeclaration()
3876{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003877 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003878}
3879
Olli Etuaho8a176262016-08-16 14:23:01 +03003880void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00003881{
Jamie Madillacb4b812016-11-07 13:50:29 -05003882 if (!sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +05303883 {
Olli Etuaho8a176262016-08-16 14:23:01 +03003884 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003885 }
3886
Arun Patole7e7e68d2015-05-22 12:02:25 +05303887 if (field.type()->getBasicType() != EbtStruct)
3888 {
Olli Etuaho8a176262016-08-16 14:23:01 +03003889 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003890 }
3891
3892 // We're already inside a structure definition at this point, so add
3893 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05303894 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
3895 {
Jonah Ryan-Davisf563fdc2019-01-31 13:53:59 -05003896 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
Olli Etuahof0957992017-12-22 11:10:04 +02003897 if (field.type()->getStruct()->symbolType() == SymbolType::Empty)
3898 {
3899 // This may happen in case there are nested struct definitions. While they are also
3900 // invalid GLSL, they don't cause a syntax error.
3901 reasonStream << "Struct nesting";
3902 }
3903 else
3904 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02003905 reasonStream << "Reference of struct type " << field.type()->getStruct()->name();
Olli Etuahof0957992017-12-22 11:10:04 +02003906 }
3907 reasonStream << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04003908 std::string reason = reasonStream.str();
Olli Etuahofbb1c792018-01-19 16:26:59 +02003909 error(line, reason.c_str(), field.name());
Olli Etuaho8a176262016-08-16 14:23:01 +03003910 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00003911 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00003912}
3913
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00003914//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003915// Parse an array index expression
3916//
Jamie Madillb98c3a82015-07-23 14:26:04 -04003917TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
3918 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303919 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003920{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003921 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
3922 {
3923 if (baseExpression->getAsSymbolNode())
3924 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303925 error(location, " left of '[' is not of type array, matrix, or vector ",
Olli Etuahofbb1c792018-01-19 16:26:59 +02003926 baseExpression->getAsSymbolNode()->getName());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003927 }
3928 else
3929 {
3930 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
3931 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003932
Olli Etuaho3ec75682017-07-05 17:02:55 +03003933 return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003934 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00003935
Jiawei Shaod8105a02017-08-08 09:54:36 +08003936 if (baseExpression->getQualifier() == EvqPerVertexIn)
3937 {
Jiawei Shaobd924af2017-11-16 15:28:04 +08003938 ASSERT(mShaderType == GL_GEOMETRY_SHADER_EXT);
Jiawei Shaod8105a02017-08-08 09:54:36 +08003939 if (mGeometryShaderInputPrimitiveType == EptUndefined)
3940 {
3941 error(location, "missing input primitive declaration before indexing gl_in.", "[");
3942 return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
3943 }
3944 }
3945
Jamie Madill21c1e452014-12-29 11:33:41 -05003946 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
3947
Olli Etuaho1dfd8ae2018-10-01 15:59:59 +03003948 // ANGLE should be able to fold any constant expressions resulting in an integer - but to be
3949 // safe we don't treat "EvqConst" that's evaluated according to the spec as being sufficient
3950 // for constness. Some interpretations of the spec have allowed constant expressions with side
3951 // effects - like array length() method on a non-constant array.
Olli Etuaho36b05142015-11-12 13:10:42 +02003952 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
3953 {
3954 if (baseExpression->isInterfaceBlock())
3955 {
Jiawei Shaobd924af2017-11-16 15:28:04 +08003956 // TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Jiawei Shaod8105a02017-08-08 09:54:36 +08003957 switch (baseExpression->getQualifier())
3958 {
3959 case EvqPerVertexIn:
3960 break;
3961 case EvqUniform:
3962 case EvqBuffer:
3963 error(location,
3964 "array indexes for uniform block arrays and shader storage block arrays "
3965 "must be constant integral expressions",
3966 "[");
3967 break;
3968 default:
Jiawei Shao7e1197e2017-08-24 15:48:38 +08003969 // We can reach here only in error cases.
3970 ASSERT(mDiagnostics->numErrors() > 0);
3971 break;
Jiawei Shaod8105a02017-08-08 09:54:36 +08003972 }
Olli Etuaho36b05142015-11-12 13:10:42 +02003973 }
3974 else if (baseExpression->getQualifier() == EvqFragmentOut)
3975 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003976 error(location,
3977 "array indexes for fragment outputs must be constant integral expressions", "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02003978 }
Olli Etuaho3e960462015-11-12 15:58:39 +02003979 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
3980 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003981 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3e960462015-11-12 15:58:39 +02003982 }
Olli Etuaho36b05142015-11-12 13:10:42 +02003983 }
3984
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003985 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04003986 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003987 // If an out-of-range index is not qualified as constant, the behavior in the spec is
3988 // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
3989 // constant fold expressions that are not constant expressions). The most compatible way to
3990 // handle this case is to report a warning instead of an error and force the index to be in
3991 // the correct range.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003992 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Olli Etuaho56229f12017-07-10 14:16:33 +03003993 int index = 0;
3994 if (indexConstantUnion->getBasicType() == EbtInt)
3995 {
3996 index = indexConstantUnion->getIConst(0);
3997 }
3998 else if (indexConstantUnion->getBasicType() == EbtUInt)
3999 {
4000 index = static_cast<int>(indexConstantUnion->getUConst(0));
4001 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004002
4003 int safeIndex = -1;
4004
Olli Etuahoebee5b32017-11-23 12:56:32 +02004005 if (index < 0)
Jamie Madill7164cf42013-07-08 13:30:59 -04004006 {
Olli Etuahoebee5b32017-11-23 12:56:32 +02004007 outOfRangeError(outOfRangeIndexIsError, location, "index expression is negative", "[]");
4008 safeIndex = 0;
4009 }
4010
4011 if (!baseExpression->getType().isUnsizedArray())
4012 {
4013 if (baseExpression->isArray())
Olli Etuaho90892fb2016-07-14 14:44:51 +03004014 {
Olli Etuahoebee5b32017-11-23 12:56:32 +02004015 if (baseExpression->getQualifier() == EvqFragData && index > 0)
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004016 {
Olli Etuahoebee5b32017-11-23 12:56:32 +02004017 if (!isExtensionEnabled(TExtension::EXT_draw_buffers))
4018 {
4019 outOfRangeError(outOfRangeIndexIsError, location,
4020 "array index for gl_FragData must be zero when "
4021 "GL_EXT_draw_buffers is disabled",
4022 "[]");
4023 safeIndex = 0;
4024 }
4025 }
Olli Etuahof13cadd2017-11-28 10:53:09 +02004026 }
4027 // Only do generic out-of-range check if similar error hasn't already been reported.
4028 if (safeIndex < 0)
4029 {
4030 if (baseExpression->isArray())
Olli Etuahoebee5b32017-11-23 12:56:32 +02004031 {
4032 safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
4033 baseExpression->getOutermostArraySize(),
4034 "array index out of range");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004035 }
Olli Etuahof13cadd2017-11-28 10:53:09 +02004036 else if (baseExpression->isMatrix())
4037 {
4038 safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
4039 baseExpression->getType().getCols(),
4040 "matrix field selection out of range");
4041 }
4042 else
4043 {
4044 ASSERT(baseExpression->isVector());
4045 safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
4046 baseExpression->getType().getNominalSize(),
4047 "vector field selection out of range");
4048 }
Olli Etuahoebee5b32017-11-23 12:56:32 +02004049 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004050
Olli Etuahoebee5b32017-11-23 12:56:32 +02004051 ASSERT(safeIndex >= 0);
4052 // Data of constant unions can't be changed, because it may be shared with other
4053 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
4054 // sanitized object.
4055 if (safeIndex != index || indexConstantUnion->getBasicType() != EbtInt)
4056 {
4057 TConstantUnion *safeConstantUnion = new TConstantUnion();
4058 safeConstantUnion->setIConst(safeIndex);
Olli Etuaho0e99b7a2018-01-12 12:05:48 +02004059 indexExpression = new TIntermConstantUnion(
4060 safeConstantUnion, TType(EbtInt, indexExpression->getPrecision(),
4061 indexExpression->getQualifier()));
Olli Etuahoebee5b32017-11-23 12:56:32 +02004062 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004063
Olli Etuahoebee5b32017-11-23 12:56:32 +02004064 TIntermBinary *node =
4065 new TIntermBinary(EOpIndexDirect, baseExpression, indexExpression);
4066 node->setLine(location);
Olli Etuahoea22b7a2018-01-04 17:09:11 +02004067 return expressionOrFoldedResult(node);
Olli Etuahoebee5b32017-11-23 12:56:32 +02004068 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004069 }
Olli Etuahoebee5b32017-11-23 12:56:32 +02004070
Olli Etuaho94bbed12018-03-20 14:44:53 +02004071 markStaticReadIfSymbol(indexExpression);
Olli Etuahoebee5b32017-11-23 12:56:32 +02004072 TIntermBinary *node = new TIntermBinary(EOpIndexIndirect, baseExpression, indexExpression);
4073 node->setLine(location);
4074 // Indirect indexing can never be constant folded.
4075 return node;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004076}
4077
Olli Etuahoebee5b32017-11-23 12:56:32 +02004078int TParseContext::checkIndexLessThan(bool outOfRangeIndexIsError,
4079 const TSourceLoc &location,
4080 int index,
4081 int arraySize,
4082 const char *reason)
Olli Etuaho90892fb2016-07-14 14:44:51 +03004083{
Olli Etuahoebee5b32017-11-23 12:56:32 +02004084 // Should not reach here with an unsized / runtime-sized array.
4085 ASSERT(arraySize > 0);
Olli Etuahof13cadd2017-11-28 10:53:09 +02004086 // A negative index should already have been checked.
4087 ASSERT(index >= 0);
Olli Etuahoebee5b32017-11-23 12:56:32 +02004088 if (index >= arraySize)
Olli Etuaho90892fb2016-07-14 14:44:51 +03004089 {
Jonah Ryan-Davisf563fdc2019-01-31 13:53:59 -05004090 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
Olli Etuaho4de340a2016-12-16 09:32:03 +00004091 reasonStream << reason << " '" << index << "'";
4092 std::string token = reasonStream.str();
4093 outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
Olli Etuahoebee5b32017-11-23 12:56:32 +02004094 return arraySize - 1;
Olli Etuaho90892fb2016-07-14 14:44:51 +03004095 }
4096 return index;
4097}
4098
Jamie Madillb98c3a82015-07-23 14:26:04 -04004099TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
4100 const TSourceLoc &dotLocation,
Olli Etuahofbb1c792018-01-19 16:26:59 +02004101 const ImmutableString &fieldString,
Jamie Madillb98c3a82015-07-23 14:26:04 -04004102 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004103{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004104 if (baseExpression->isArray())
4105 {
4106 error(fieldLocation, "cannot apply dot operator to an array", ".");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004107 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004108 }
4109
4110 if (baseExpression->isVector())
4111 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004112 TVector<int> fieldOffsets;
4113 if (!parseVectorFields(fieldLocation, fieldString, baseExpression->getNominalSize(),
4114 &fieldOffsets))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004115 {
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004116 fieldOffsets.resize(1);
4117 fieldOffsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004118 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004119 TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldOffsets);
4120 node->setLine(dotLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004121
Olli Etuaho765924f2018-01-04 12:48:36 +02004122 return node->fold(mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004123 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004124 else if (baseExpression->getBasicType() == EbtStruct)
4125 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05304126 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04004127 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004128 {
4129 error(dotLocation, "structure has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004130 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004131 }
4132 else
4133 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004134 bool fieldFound = false;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004135 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04004136 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004137 {
Jamie Madill98493dd2013-07-08 14:39:03 -04004138 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004139 {
4140 fieldFound = true;
4141 break;
4142 }
4143 }
4144 if (fieldFound)
4145 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03004146 TIntermTyped *index = CreateIndexNode(i);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004147 index->setLine(fieldLocation);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004148 TIntermBinary *node =
4149 new TIntermBinary(EOpIndexDirectStruct, baseExpression, index);
4150 node->setLine(dotLocation);
Olli Etuahoea22b7a2018-01-04 17:09:11 +02004151 return expressionOrFoldedResult(node);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004152 }
4153 else
4154 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02004155 error(dotLocation, " no such field in structure", fieldString);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004156 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004157 }
4158 }
4159 }
Jamie Madill98493dd2013-07-08 14:39:03 -04004160 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004161 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05304162 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04004163 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004164 {
4165 error(dotLocation, "interface block has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004166 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004167 }
4168 else
4169 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004170 bool fieldFound = false;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004171 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04004172 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004173 {
Jamie Madill98493dd2013-07-08 14:39:03 -04004174 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004175 {
4176 fieldFound = true;
4177 break;
4178 }
4179 }
4180 if (fieldFound)
4181 {
Olli Etuaho3ec75682017-07-05 17:02:55 +03004182 TIntermTyped *index = CreateIndexNode(i);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004183 index->setLine(fieldLocation);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004184 TIntermBinary *node =
4185 new TIntermBinary(EOpIndexDirectInterfaceBlock, baseExpression, index);
4186 node->setLine(dotLocation);
4187 // Indexing interface blocks can never be constant folded.
4188 return node;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004189 }
4190 else
4191 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02004192 error(dotLocation, " no such field in interface block", fieldString);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004193 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004194 }
4195 }
4196 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004197 else
4198 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004199 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004200 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03004201 error(dotLocation, " field selection requires structure or vector on left hand side",
Olli Etuahofbb1c792018-01-19 16:26:59 +02004202 fieldString);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004203 }
4204 else
4205 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05304206 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03004207 " field selection requires structure, vector, or interface block on left hand "
4208 "side",
Olli Etuahofbb1c792018-01-19 16:26:59 +02004209 fieldString);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00004210 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03004211 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004212 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004213}
4214
Olli Etuahofbb1c792018-01-19 16:26:59 +02004215TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qualifierType,
Jamie Madillb98c3a82015-07-23 14:26:04 -04004216 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004217{
Jamie Madill2f294c92017-11-20 14:47:26 -05004218 TLayoutQualifier qualifier = TLayoutQualifier::Create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004219
4220 if (qualifierType == "shared")
4221 {
Jamie Madillacb4b812016-11-07 13:50:29 -05004222 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07004223 {
4224 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
4225 }
Jamie Madilla5efff92013-06-06 11:56:47 -04004226 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004227 }
4228 else if (qualifierType == "packed")
4229 {
Jamie Madillacb4b812016-11-07 13:50:29 -05004230 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07004231 {
4232 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
4233 }
Jamie Madilla5efff92013-06-06 11:56:47 -04004234 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004235 }
Qin Jiajiaca68d982017-09-18 16:41:56 +08004236 else if (qualifierType == "std430")
4237 {
4238 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4239 qualifier.blockStorage = EbsStd430;
4240 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004241 else if (qualifierType == "std140")
4242 {
Jamie Madilla5efff92013-06-06 11:56:47 -04004243 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004244 }
4245 else if (qualifierType == "row_major")
4246 {
Jamie Madilla5efff92013-06-06 11:56:47 -04004247 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004248 }
4249 else if (qualifierType == "column_major")
4250 {
Jamie Madilla5efff92013-06-06 11:56:47 -04004251 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004252 }
4253 else if (qualifierType == "location")
4254 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00004255 error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
Olli Etuahofbb1c792018-01-19 16:26:59 +02004256 qualifierType);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004257 }
Olli Etuaho703671e2017-11-08 17:47:18 +02004258 else if (qualifierType == "yuv" && mShaderType == GL_FRAGMENT_SHADER)
Andrei Volykhina5527072017-03-22 16:46:30 +03004259 {
Olli Etuaho703671e2017-11-08 17:47:18 +02004260 if (checkCanUseExtension(qualifierTypeLine, TExtension::EXT_YUV_target))
4261 {
4262 qualifier.yuv = true;
4263 }
Andrei Volykhina5527072017-03-22 16:46:30 +03004264 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004265 else if (qualifierType == "rgba32f")
4266 {
4267 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4268 qualifier.imageInternalFormat = EiifRGBA32F;
4269 }
4270 else if (qualifierType == "rgba16f")
4271 {
4272 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4273 qualifier.imageInternalFormat = EiifRGBA16F;
4274 }
4275 else if (qualifierType == "r32f")
4276 {
4277 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4278 qualifier.imageInternalFormat = EiifR32F;
4279 }
4280 else if (qualifierType == "rgba8")
4281 {
4282 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4283 qualifier.imageInternalFormat = EiifRGBA8;
4284 }
4285 else if (qualifierType == "rgba8_snorm")
4286 {
4287 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4288 qualifier.imageInternalFormat = EiifRGBA8_SNORM;
4289 }
4290 else if (qualifierType == "rgba32i")
4291 {
4292 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4293 qualifier.imageInternalFormat = EiifRGBA32I;
4294 }
4295 else if (qualifierType == "rgba16i")
4296 {
4297 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4298 qualifier.imageInternalFormat = EiifRGBA16I;
4299 }
4300 else if (qualifierType == "rgba8i")
4301 {
4302 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4303 qualifier.imageInternalFormat = EiifRGBA8I;
4304 }
4305 else if (qualifierType == "r32i")
4306 {
4307 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4308 qualifier.imageInternalFormat = EiifR32I;
4309 }
4310 else if (qualifierType == "rgba32ui")
4311 {
4312 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4313 qualifier.imageInternalFormat = EiifRGBA32UI;
4314 }
4315 else if (qualifierType == "rgba16ui")
4316 {
4317 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4318 qualifier.imageInternalFormat = EiifRGBA16UI;
4319 }
4320 else if (qualifierType == "rgba8ui")
4321 {
4322 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4323 qualifier.imageInternalFormat = EiifRGBA8UI;
4324 }
4325 else if (qualifierType == "r32ui")
4326 {
4327 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4328 qualifier.imageInternalFormat = EiifR32UI;
4329 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004330 else if (qualifierType == "points" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4331 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004332 {
4333 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4334 qualifier.primitiveType = EptPoints;
4335 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004336 else if (qualifierType == "lines" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4337 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004338 {
4339 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4340 qualifier.primitiveType = EptLines;
4341 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004342 else if (qualifierType == "lines_adjacency" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4343 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004344 {
4345 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4346 qualifier.primitiveType = EptLinesAdjacency;
4347 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004348 else if (qualifierType == "triangles" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4349 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004350 {
4351 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4352 qualifier.primitiveType = EptTriangles;
4353 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004354 else if (qualifierType == "triangles_adjacency" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4355 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004356 {
4357 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4358 qualifier.primitiveType = EptTrianglesAdjacency;
4359 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004360 else if (qualifierType == "line_strip" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4361 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004362 {
4363 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4364 qualifier.primitiveType = EptLineStrip;
4365 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004366 else if (qualifierType == "triangle_strip" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4367 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004368 {
4369 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4370 qualifier.primitiveType = EptTriangleStrip;
4371 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004372
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004373 else
4374 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02004375 error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004376 }
4377
Jamie Madilla5efff92013-06-06 11:56:47 -04004378 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004379}
4380
Olli Etuahofbb1c792018-01-19 16:26:59 +02004381void TParseContext::parseLocalSize(const ImmutableString &qualifierType,
Martin Radev802abe02016-08-04 17:48:32 +03004382 const TSourceLoc &qualifierTypeLine,
4383 int intValue,
4384 const TSourceLoc &intValueLine,
4385 const std::string &intValueString,
4386 size_t index,
Martin Radev4c4c8e72016-08-04 12:25:34 +03004387 sh::WorkGroupSize *localSize)
Martin Radev802abe02016-08-04 17:48:32 +03004388{
Olli Etuaho856c4972016-08-08 11:38:39 +03004389 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03004390 if (intValue < 1)
4391 {
Jonah Ryan-Davisf563fdc2019-01-31 13:53:59 -05004392 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
Olli Etuaho4de340a2016-12-16 09:32:03 +00004393 reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
4394 std::string reason = reasonStream.str();
4395 error(intValueLine, reason.c_str(), intValueString.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03004396 }
4397 (*localSize)[index] = intValue;
4398}
4399
Olli Etuaho09b04a22016-12-15 13:30:26 +00004400void TParseContext::parseNumViews(int intValue,
4401 const TSourceLoc &intValueLine,
4402 const std::string &intValueString,
4403 int *numViews)
4404{
4405 // This error is only specified in WebGL, but tightens unspecified behavior in the native
4406 // specification.
4407 if (intValue < 1)
4408 {
4409 error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
4410 }
4411 *numViews = intValue;
4412}
4413
Shaob5cc1192017-07-06 10:47:20 +08004414void TParseContext::parseInvocations(int intValue,
4415 const TSourceLoc &intValueLine,
4416 const std::string &intValueString,
4417 int *numInvocations)
4418{
4419 // Although SPEC isn't clear whether invocations can be less than 1, we add this limit because
4420 // it doesn't make sense to accept invocations <= 0.
4421 if (intValue < 1 || intValue > mMaxGeometryShaderInvocations)
4422 {
4423 error(intValueLine,
4424 "out of range: invocations must be in the range of [1, "
4425 "MAX_GEOMETRY_SHADER_INVOCATIONS_OES]",
4426 intValueString.c_str());
4427 }
4428 else
4429 {
4430 *numInvocations = intValue;
4431 }
4432}
4433
4434void TParseContext::parseMaxVertices(int intValue,
4435 const TSourceLoc &intValueLine,
4436 const std::string &intValueString,
4437 int *maxVertices)
4438{
4439 // Although SPEC isn't clear whether max_vertices can be less than 0, we add this limit because
4440 // it doesn't make sense to accept max_vertices < 0.
4441 if (intValue < 0 || intValue > mMaxGeometryShaderMaxVertices)
4442 {
4443 error(
4444 intValueLine,
4445 "out of range: max_vertices must be in the range of [0, gl_MaxGeometryOutputVertices]",
4446 intValueString.c_str());
4447 }
4448 else
4449 {
4450 *maxVertices = intValue;
4451 }
4452}
4453
Olli Etuahoa78092c2018-09-26 14:16:13 +03004454void TParseContext::parseIndexLayoutQualifier(int intValue,
4455 const TSourceLoc &intValueLine,
4456 const std::string &intValueString,
4457 int *index)
4458{
4459 // EXT_blend_func_extended specifies that most validation should happen at link time, but since
4460 // we're validating output variable locations at compile time, it makes sense to validate that
4461 // index is 0 or 1 also at compile time. Also since we use "-1" as a placeholder for unspecified
4462 // index, we can't accept it here.
4463 if (intValue < 0 || intValue > 1)
4464 {
4465 error(intValueLine, "out of range: index layout qualifier can only be 0 or 1",
4466 intValueString.c_str());
4467 }
4468 else
4469 {
4470 *index = intValue;
4471 }
4472}
4473
Olli Etuahofbb1c792018-01-19 16:26:59 +02004474TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qualifierType,
Jamie Madillb98c3a82015-07-23 14:26:04 -04004475 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04004476 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05304477 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004478{
Jamie Madill2f294c92017-11-20 14:47:26 -05004479 TLayoutQualifier qualifier = TLayoutQualifier::Create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004480
Martin Radev802abe02016-08-04 17:48:32 +03004481 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004482
Martin Radev802abe02016-08-04 17:48:32 +03004483 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004484 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04004485 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004486 if (intValue < 0)
4487 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00004488 error(intValueLine, "out of range: location must be non-negative",
4489 intValueString.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004490 }
4491 else
4492 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05004493 qualifier.location = intValue;
Olli Etuaho87d410c2016-09-05 13:33:26 +03004494 qualifier.locationsSpecified = 1;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004495 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004496 }
Olli Etuaho43364892017-02-13 16:00:12 +00004497 else if (qualifierType == "binding")
4498 {
4499 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4500 if (intValue < 0)
4501 {
4502 error(intValueLine, "out of range: binding must be non-negative",
4503 intValueString.c_str());
4504 }
4505 else
4506 {
4507 qualifier.binding = intValue;
4508 }
4509 }
jchen104cdac9e2017-05-08 11:01:20 +08004510 else if (qualifierType == "offset")
4511 {
4512 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
4513 if (intValue < 0)
4514 {
4515 error(intValueLine, "out of range: offset must be non-negative",
4516 intValueString.c_str());
4517 }
4518 else
4519 {
4520 qualifier.offset = intValue;
4521 }
4522 }
Martin Radev802abe02016-08-04 17:48:32 +03004523 else if (qualifierType == "local_size_x")
4524 {
4525 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
4526 &qualifier.localSize);
4527 }
4528 else if (qualifierType == "local_size_y")
4529 {
4530 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
4531 &qualifier.localSize);
4532 }
4533 else if (qualifierType == "local_size_z")
4534 {
4535 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
4536 &qualifier.localSize);
4537 }
Olli Etuaho703671e2017-11-08 17:47:18 +02004538 else if (qualifierType == "num_views" && mShaderType == GL_VERTEX_SHADER)
Olli Etuaho09b04a22016-12-15 13:30:26 +00004539 {
Mingyu Huebab6702019-04-19 14:36:45 -07004540 if (checkCanUseOneOfExtensions(
4541 qualifierTypeLine, std::array<TExtension, 2u>{
4542 {TExtension::OVR_multiview, TExtension::OVR_multiview2}}))
Olli Etuaho703671e2017-11-08 17:47:18 +02004543 {
4544 parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
4545 }
Olli Etuaho09b04a22016-12-15 13:30:26 +00004546 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004547 else if (qualifierType == "invocations" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4548 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004549 {
4550 parseInvocations(intValue, intValueLine, intValueString, &qualifier.invocations);
4551 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004552 else if (qualifierType == "max_vertices" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4553 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_geometry_shader))
Shaob5cc1192017-07-06 10:47:20 +08004554 {
4555 parseMaxVertices(intValue, intValueLine, intValueString, &qualifier.maxVertices);
4556 }
Olli Etuahoa78092c2018-09-26 14:16:13 +03004557 else if (qualifierType == "index" && mShaderType == GL_FRAGMENT_SHADER &&
4558 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_blend_func_extended))
4559 {
4560 parseIndexLayoutQualifier(intValue, intValueLine, intValueString, &qualifier.index);
4561 }
Martin Radev802abe02016-08-04 17:48:32 +03004562 else
4563 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02004564 error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
Martin Radev802abe02016-08-04 17:48:32 +03004565 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004566
Jamie Madilla5efff92013-06-06 11:56:47 -04004567 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004568}
4569
Olli Etuaho613b9592016-09-05 12:05:53 +03004570TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
4571{
4572 return new TTypeQualifierBuilder(
4573 new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
4574 mShaderVersion);
4575}
4576
Olli Etuahocce89652017-06-19 16:04:09 +03004577TStorageQualifierWrapper *TParseContext::parseGlobalStorageQualifier(TQualifier qualifier,
4578 const TSourceLoc &loc)
4579{
4580 checkIsAtGlobalLevel(loc, getQualifierString(qualifier));
4581 return new TStorageQualifierWrapper(qualifier, loc);
4582}
4583
4584TStorageQualifierWrapper *TParseContext::parseVaryingQualifier(const TSourceLoc &loc)
4585{
4586 if (getShaderType() == GL_VERTEX_SHADER)
4587 {
4588 return parseGlobalStorageQualifier(EvqVaryingOut, loc);
4589 }
4590 return parseGlobalStorageQualifier(EvqVaryingIn, loc);
4591}
4592
4593TStorageQualifierWrapper *TParseContext::parseInQualifier(const TSourceLoc &loc)
4594{
4595 if (declaringFunction())
4596 {
4597 return new TStorageQualifierWrapper(EvqIn, loc);
4598 }
Shaob5cc1192017-07-06 10:47:20 +08004599
4600 switch (getShaderType())
Olli Etuahocce89652017-06-19 16:04:09 +03004601 {
Shaob5cc1192017-07-06 10:47:20 +08004602 case GL_VERTEX_SHADER:
Olli Etuahocce89652017-06-19 16:04:09 +03004603 {
Mingyu Huebab6702019-04-19 14:36:45 -07004604 if (mShaderVersion < 300 && !anyMultiviewExtensionAvailable())
Shaob5cc1192017-07-06 10:47:20 +08004605 {
4606 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
4607 }
4608 return new TStorageQualifierWrapper(EvqVertexIn, loc);
Olli Etuahocce89652017-06-19 16:04:09 +03004609 }
Shaob5cc1192017-07-06 10:47:20 +08004610 case GL_FRAGMENT_SHADER:
Olli Etuahocce89652017-06-19 16:04:09 +03004611 {
Shaob5cc1192017-07-06 10:47:20 +08004612 if (mShaderVersion < 300)
4613 {
4614 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
4615 }
4616 return new TStorageQualifierWrapper(EvqFragmentIn, loc);
Olli Etuahocce89652017-06-19 16:04:09 +03004617 }
Shaob5cc1192017-07-06 10:47:20 +08004618 case GL_COMPUTE_SHADER:
4619 {
4620 return new TStorageQualifierWrapper(EvqComputeIn, loc);
4621 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004622 case GL_GEOMETRY_SHADER_EXT:
Shaob5cc1192017-07-06 10:47:20 +08004623 {
4624 return new TStorageQualifierWrapper(EvqGeometryIn, loc);
4625 }
4626 default:
4627 {
4628 UNREACHABLE();
4629 return new TStorageQualifierWrapper(EvqLast, loc);
4630 }
Olli Etuahocce89652017-06-19 16:04:09 +03004631 }
Olli Etuahocce89652017-06-19 16:04:09 +03004632}
4633
4634TStorageQualifierWrapper *TParseContext::parseOutQualifier(const TSourceLoc &loc)
4635{
4636 if (declaringFunction())
4637 {
4638 return new TStorageQualifierWrapper(EvqOut, loc);
4639 }
Shaob5cc1192017-07-06 10:47:20 +08004640 switch (getShaderType())
Olli Etuahocce89652017-06-19 16:04:09 +03004641 {
Shaob5cc1192017-07-06 10:47:20 +08004642 case GL_VERTEX_SHADER:
4643 {
4644 if (mShaderVersion < 300)
4645 {
4646 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
4647 }
4648 return new TStorageQualifierWrapper(EvqVertexOut, loc);
4649 }
4650 case GL_FRAGMENT_SHADER:
4651 {
4652 if (mShaderVersion < 300)
4653 {
4654 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
4655 }
4656 return new TStorageQualifierWrapper(EvqFragmentOut, loc);
4657 }
4658 case GL_COMPUTE_SHADER:
4659 {
4660 error(loc, "storage qualifier isn't supported in compute shaders", "out");
4661 return new TStorageQualifierWrapper(EvqLast, loc);
4662 }
Jiawei Shaobd924af2017-11-16 15:28:04 +08004663 case GL_GEOMETRY_SHADER_EXT:
Shaob5cc1192017-07-06 10:47:20 +08004664 {
4665 return new TStorageQualifierWrapper(EvqGeometryOut, loc);
4666 }
4667 default:
4668 {
4669 UNREACHABLE();
4670 return new TStorageQualifierWrapper(EvqLast, loc);
4671 }
Olli Etuahocce89652017-06-19 16:04:09 +03004672 }
Olli Etuahocce89652017-06-19 16:04:09 +03004673}
4674
4675TStorageQualifierWrapper *TParseContext::parseInOutQualifier(const TSourceLoc &loc)
4676{
4677 if (!declaringFunction())
4678 {
4679 error(loc, "invalid qualifier: can be only used with function parameters", "inout");
4680 }
4681 return new TStorageQualifierWrapper(EvqInOut, loc);
4682}
4683
Jamie Madillb98c3a82015-07-23 14:26:04 -04004684TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03004685 TLayoutQualifier rightQualifier,
4686 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004687{
Martin Radevc28888b2016-07-22 15:27:42 +03004688 return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
Olli Etuaho77ba4082016-12-16 12:01:18 +00004689 mDiagnostics);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00004690}
4691
Olli Etuahofbb1c792018-01-19 16:26:59 +02004692TDeclarator *TParseContext::parseStructDeclarator(const ImmutableString &identifier,
4693 const TSourceLoc &loc)
Olli Etuahocce89652017-06-19 16:04:09 +03004694{
Olli Etuahofbb1c792018-01-19 16:26:59 +02004695 checkIsNotReserved(loc, identifier);
Olli Etuahod5f44c92017-11-29 17:15:40 +02004696 return new TDeclarator(identifier, loc);
Olli Etuahocce89652017-06-19 16:04:09 +03004697}
4698
Olli Etuahofbb1c792018-01-19 16:26:59 +02004699TDeclarator *TParseContext::parseStructArrayDeclarator(const ImmutableString &identifier,
Olli Etuahod5f44c92017-11-29 17:15:40 +02004700 const TSourceLoc &loc,
4701 const TVector<unsigned int> *arraySizes)
Olli Etuahocce89652017-06-19 16:04:09 +03004702{
Olli Etuahofbb1c792018-01-19 16:26:59 +02004703 checkIsNotReserved(loc, identifier);
Olli Etuahod5f44c92017-11-29 17:15:40 +02004704 return new TDeclarator(identifier, arraySizes, loc);
Olli Etuahocce89652017-06-19 16:04:09 +03004705}
4706
Olli Etuaho722bfb52017-10-26 17:00:11 +03004707void TParseContext::checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin,
4708 const TFieldList::const_iterator end,
Olli Etuahofbb1c792018-01-19 16:26:59 +02004709 const ImmutableString &name,
Olli Etuaho722bfb52017-10-26 17:00:11 +03004710 const TSourceLoc &location)
4711{
4712 for (auto fieldIter = begin; fieldIter != end; ++fieldIter)
4713 {
4714 if ((*fieldIter)->name() == name)
4715 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02004716 error(location, "duplicate field name in structure", name);
Olli Etuaho722bfb52017-10-26 17:00:11 +03004717 }
4718 }
4719}
4720
4721TFieldList *TParseContext::addStructFieldList(TFieldList *fields, const TSourceLoc &location)
4722{
4723 for (TFieldList::const_iterator fieldIter = fields->begin(); fieldIter != fields->end();
4724 ++fieldIter)
4725 {
4726 checkDoesNotHaveDuplicateFieldName(fields->begin(), fieldIter, (*fieldIter)->name(),
4727 location);
4728 }
4729 return fields;
4730}
4731
Olli Etuaho4de340a2016-12-16 09:32:03 +00004732TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
4733 const TFieldList *newlyAddedFields,
4734 const TSourceLoc &location)
4735{
4736 for (TField *field : *newlyAddedFields)
4737 {
Olli Etuaho722bfb52017-10-26 17:00:11 +03004738 checkDoesNotHaveDuplicateFieldName(processedFields->begin(), processedFields->end(),
4739 field->name(), location);
Olli Etuaho4de340a2016-12-16 09:32:03 +00004740 processedFields->push_back(field);
4741 }
4742 return processedFields;
4743}
4744
Martin Radev70866b82016-07-22 15:27:42 +03004745TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
4746 const TTypeQualifierBuilder &typeQualifierBuilder,
4747 TPublicType *typeSpecifier,
Olli Etuahod5f44c92017-11-29 17:15:40 +02004748 const TDeclaratorList *declaratorList)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04004749{
Olli Etuaho77ba4082016-12-16 12:01:18 +00004750 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04004751
Martin Radev70866b82016-07-22 15:27:42 +03004752 typeSpecifier->qualifier = typeQualifier.qualifier;
4753 typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03004754 typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03004755 typeSpecifier->invariant = typeQualifier.invariant;
4756 if (typeQualifier.precision != EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +05304757 {
Martin Radev70866b82016-07-22 15:27:42 +03004758 typeSpecifier->precision = typeQualifier.precision;
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04004759 }
Olli Etuahod5f44c92017-11-29 17:15:40 +02004760 return addStructDeclaratorList(*typeSpecifier, declaratorList);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04004761}
4762
Jamie Madillb98c3a82015-07-23 14:26:04 -04004763TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
Olli Etuahod5f44c92017-11-29 17:15:40 +02004764 const TDeclaratorList *declaratorList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004765{
Martin Radev4a9cd802016-09-01 16:51:51 +03004766 checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
4767 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03004768
Olli Etuahofbb1c792018-01-19 16:26:59 +02004769 checkIsNonVoid(typeSpecifier.getLine(), (*declaratorList)[0]->name(),
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004770 typeSpecifier.getBasicType());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004771
Martin Radev4a9cd802016-09-01 16:51:51 +03004772 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03004773
Olli Etuahod5f44c92017-11-29 17:15:40 +02004774 TFieldList *fieldList = new TFieldList();
4775
4776 for (const TDeclarator *declarator : *declaratorList)
Arun Patole7e7e68d2015-05-22 12:02:25 +05304777 {
Olli Etuahod5f44c92017-11-29 17:15:40 +02004778 TType *type = new TType(typeSpecifier);
4779 if (declarator->isArray())
Arun Patole7e7e68d2015-05-22 12:02:25 +05304780 {
Olli Etuahod5f44c92017-11-29 17:15:40 +02004781 // Don't allow arrays of arrays in ESSL < 3.10.
Olli Etuahoe0803872017-08-23 15:30:23 +03004782 checkArrayElementIsNotArray(typeSpecifier.getLine(), typeSpecifier);
Olli Etuahod5f44c92017-11-29 17:15:40 +02004783 type->makeArrays(*declarator->arraySizes());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004784 }
Olli Etuaho96f6adf2017-08-16 11:18:54 +03004785
Jamie Madillf5557ac2018-06-15 09:46:58 -04004786 TField *field =
4787 new TField(type, declarator->name(), declarator->line(), SymbolType::UserDefined);
Olli Etuahod5f44c92017-11-29 17:15:40 +02004788 checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *field);
4789 fieldList->push_back(field);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004790 }
4791
Olli Etuahod5f44c92017-11-29 17:15:40 +02004792 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004793}
4794
Martin Radev4a9cd802016-09-01 16:51:51 +03004795TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
4796 const TSourceLoc &nameLine,
Olli Etuahofbb1c792018-01-19 16:26:59 +02004797 const ImmutableString &structName,
Martin Radev4a9cd802016-09-01 16:51:51 +03004798 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004799{
Olli Etuaho9d4d7f02017-12-07 17:11:41 +01004800 SymbolType structSymbolType = SymbolType::UserDefined;
Olli Etuahofbb1c792018-01-19 16:26:59 +02004801 if (structName.empty())
Olli Etuaho9d4d7f02017-12-07 17:11:41 +01004802 {
Olli Etuaho9d4d7f02017-12-07 17:11:41 +01004803 structSymbolType = SymbolType::Empty;
4804 }
4805 TStructure *structure = new TStructure(&symbolTable, structName, fieldList, structSymbolType);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004806
Jamie Madill9b820842015-02-12 10:40:10 -05004807 // Store a bool in the struct if we're at global scope, to allow us to
4808 // skip the local struct scoping workaround in HLSL.
Jamie Madill9b820842015-02-12 10:40:10 -05004809 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04004810
Olli Etuaho9d4d7f02017-12-07 17:11:41 +01004811 if (structSymbolType != SymbolType::Empty)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004812 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02004813 checkIsNotReserved(nameLine, structName);
Olli Etuaho437664b2018-02-28 15:38:14 +02004814 if (!symbolTable.declare(structure))
Arun Patole7e7e68d2015-05-22 12:02:25 +05304815 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02004816 error(nameLine, "redefinition of a struct", structName);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004817 }
4818 }
4819
4820 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04004821 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004822 {
Olli Etuahoebee5b32017-11-23 12:56:32 +02004823 TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04004824 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004825 switch (qualifier)
4826 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004827 case EvqGlobal:
4828 case EvqTemporary:
4829 break;
4830 default:
4831 error(field.line(), "invalid qualifier on struct member",
4832 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04004833 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004834 }
Martin Radev70866b82016-07-22 15:27:42 +03004835 if (field.type()->isInvariant())
4836 {
4837 error(field.line(), "invalid qualifier on struct member", "invariant");
4838 }
jchen104cdac9e2017-05-08 11:01:20 +08004839 // ESSL 3.10 section 4.1.8 -- atomic_uint or images are not allowed as structure member.
4840 if (IsImage(field.type()->getBasicType()) || IsAtomicCounter(field.type()->getBasicType()))
Martin Radev2cc85b32016-08-05 16:22:53 +03004841 {
4842 error(field.line(), "disallowed type in struct", field.type()->getBasicString());
4843 }
4844
Olli Etuahoebee5b32017-11-23 12:56:32 +02004845 checkIsNotUnsizedArray(field.line(), "array members of structs must specify a size",
Olli Etuahofbb1c792018-01-19 16:26:59 +02004846 field.name(), field.type());
Olli Etuahoebee5b32017-11-23 12:56:32 +02004847
Olli Etuaho43364892017-02-13 16:00:12 +00004848 checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
4849
Olli Etuahoa78092c2018-09-26 14:16:13 +03004850 checkIndexIsNotSpecified(field.line(), field.type()->getLayoutQualifier().index);
4851
Olli Etuaho43364892017-02-13 16:00:12 +00004852 checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);
Martin Radev70866b82016-07-22 15:27:42 +03004853
4854 checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004855 }
4856
Martin Radev4a9cd802016-09-01 16:51:51 +03004857 TTypeSpecifierNonArray typeSpecifierNonArray;
Olli Etuaho0f684632017-07-13 12:42:15 +03004858 typeSpecifierNonArray.initializeStruct(structure, true, structLine);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004859 exitStructDeclaration();
4860
Martin Radev4a9cd802016-09-01 16:51:51 +03004861 return typeSpecifierNonArray;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004862}
4863
Jamie Madillb98c3a82015-07-23 14:26:04 -04004864TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01004865 TIntermBlock *statementList,
Jamie Madillb98c3a82015-07-23 14:26:04 -04004866 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02004867{
Olli Etuaho53f076f2015-02-20 10:55:14 +02004868 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04004869 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02004870 init->isVector())
4871 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004872 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
4873 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004874 return nullptr;
4875 }
4876
Olli Etuaho923ecef2017-10-11 12:01:38 +03004877 ASSERT(statementList);
Olli Etuahod05f9642018-03-05 12:13:26 +02004878 if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
Olli Etuahoac5274d2015-02-20 10:19:08 +02004879 {
Olli Etuahocbcb96f2017-10-19 14:14:06 +03004880 ASSERT(mDiagnostics->numErrors() > 0);
Olli Etuaho923ecef2017-10-11 12:01:38 +03004881 return nullptr;
Olli Etuahoac5274d2015-02-20 10:19:08 +02004882 }
4883
Olli Etuaho94bbed12018-03-20 14:44:53 +02004884 markStaticReadIfSymbol(init);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004885 TIntermSwitch *node = new TIntermSwitch(init, statementList);
4886 node->setLine(loc);
Olli Etuahoa3a36662015-02-17 13:46:51 +02004887 return node;
4888}
4889
4890TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
4891{
Olli Etuaho53f076f2015-02-20 10:55:14 +02004892 if (mSwitchNestingLevel == 0)
4893 {
4894 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004895 return nullptr;
4896 }
4897 if (condition == nullptr)
4898 {
4899 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004900 return nullptr;
4901 }
4902 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04004903 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02004904 {
4905 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004906 }
4907 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho1dfd8ae2018-10-01 15:59:59 +03004908 // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be
4909 // safe against corner cases we still check for conditionConst. Some interpretations of the
4910 // spec have allowed constant expressions with side effects - like array length() method on a
4911 // non-constant array.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02004912 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02004913 {
4914 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004915 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004916 TIntermCase *node = new TIntermCase(condition);
4917 node->setLine(loc);
Olli Etuahoa3a36662015-02-17 13:46:51 +02004918 return node;
4919}
4920
4921TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
4922{
Olli Etuaho53f076f2015-02-20 10:55:14 +02004923 if (mSwitchNestingLevel == 0)
4924 {
4925 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02004926 return nullptr;
4927 }
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004928 TIntermCase *node = new TIntermCase(nullptr);
4929 node->setLine(loc);
Olli Etuahoa3a36662015-02-17 13:46:51 +02004930 return node;
4931}
4932
Jamie Madillb98c3a82015-07-23 14:26:04 -04004933TIntermTyped *TParseContext::createUnaryMath(TOperator op,
4934 TIntermTyped *child,
Olli Etuaho5fec7ab2018-04-04 11:58:33 +03004935 const TSourceLoc &loc,
4936 const TFunction *func)
Olli Etuaho69c11b52015-03-26 12:59:00 +02004937{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004938 ASSERT(child != nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02004939
4940 switch (op)
4941 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004942 case EOpLogicalNot:
4943 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
4944 child->isVector())
4945 {
Olli Etuaho72e35892018-06-20 11:43:08 +03004946 unaryOpError(loc, GetOperatorString(op), child->getType());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004947 return nullptr;
4948 }
4949 break;
4950 case EOpBitwiseNot:
4951 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
4952 child->isMatrix() || child->isArray())
4953 {
Olli Etuaho72e35892018-06-20 11:43:08 +03004954 unaryOpError(loc, GetOperatorString(op), child->getType());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004955 return nullptr;
4956 }
4957 break;
4958 case EOpPostIncrement:
4959 case EOpPreIncrement:
4960 case EOpPostDecrement:
4961 case EOpPreDecrement:
4962 case EOpNegative:
4963 case EOpPositive:
Olli Etuaho94050052017-05-08 14:17:44 +03004964 if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() ||
4965 child->getBasicType() == EbtBool || child->isArray() ||
Geoff Lang6aab06e2018-11-20 14:04:11 -05004966 child->getBasicType() == EbtVoid || IsOpaqueType(child->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -04004967 {
Olli Etuaho72e35892018-06-20 11:43:08 +03004968 unaryOpError(loc, GetOperatorString(op), child->getType());
Jamie Madillb98c3a82015-07-23 14:26:04 -04004969 return nullptr;
4970 }
Nico Weber41b072b2018-02-09 10:01:32 -05004971 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04004972 // Operators for built-ins are already type checked against their prototype.
4973 default:
4974 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02004975 }
4976
Jiajia Qinbc585152017-06-23 15:42:17 +08004977 if (child->getMemoryQualifier().writeonly)
4978 {
Olli Etuaho72e35892018-06-20 11:43:08 +03004979 unaryOpError(loc, GetOperatorString(op), child->getType());
Jiajia Qinbc585152017-06-23 15:42:17 +08004980 return nullptr;
4981 }
4982
Olli Etuaho94bbed12018-03-20 14:44:53 +02004983 markStaticReadIfSymbol(child);
Olli Etuaho5fec7ab2018-04-04 11:58:33 +03004984 TIntermUnary *node = new TIntermUnary(op, child, func);
Olli Etuahof119a262016-08-19 15:54:22 +03004985 node->setLine(loc);
Olli Etuahof119a262016-08-19 15:54:22 +03004986
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03004987 return node->fold(mDiagnostics);
Olli Etuaho69c11b52015-03-26 12:59:00 +02004988}
4989
Olli Etuaho09b22472015-02-11 11:47:26 +02004990TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
4991{
Olli Etuahocce89652017-06-19 16:04:09 +03004992 ASSERT(op != EOpNull);
Olli Etuaho5fec7ab2018-04-04 11:58:33 +03004993 TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02004994 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02004995 {
Olli Etuaho09b22472015-02-11 11:47:26 +02004996 return child;
4997 }
4998 return node;
4999}
5000
Jamie Madillb98c3a82015-07-23 14:26:04 -04005001TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
5002 TIntermTyped *child,
5003 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02005004{
Olli Etuaho856c4972016-08-08 11:38:39 +03005005 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02005006 return addUnaryMath(op, child, loc);
5007}
5008
Olli Etuaho765924f2018-01-04 12:48:36 +02005009TIntermTyped *TParseContext::expressionOrFoldedResult(TIntermTyped *expression)
5010{
5011 // If we can, we should return the folded version of the expression for subsequent parsing. This
5012 // enables folding the containing expression during parsing as well, instead of the separate
5013 // FoldExpressions() step where folding nested expressions requires multiple full AST
5014 // traversals.
5015
5016 // Even if folding fails the fold() functions return some node representing the expression,
5017 // typically the original node. So "folded" can be assumed to be non-null.
5018 TIntermTyped *folded = expression->fold(mDiagnostics);
5019 ASSERT(folded != nullptr);
5020 if (folded->getQualifier() == expression->getQualifier())
5021 {
5022 // We need this expression to have the correct qualifier when validating the consuming
5023 // expression. So we can only return the folded node from here in case it has the same
5024 // qualifier as the original expression. In this kind of a cases the qualifier of the folded
5025 // node is EvqConst, whereas the qualifier of the expression is EvqTemporary:
5026 // 1. (true ? 1.0 : non_constant)
5027 // 2. (non_constant, 1.0)
5028 return folded;
5029 }
5030 return expression;
5031}
5032
Jamie Madillb98c3a82015-07-23 14:26:04 -04005033bool TParseContext::binaryOpCommonCheck(TOperator op,
5034 TIntermTyped *left,
5035 TIntermTyped *right,
5036 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02005037{
jchen10b4cf5652017-05-05 18:51:17 +08005038 // Check opaque types are not allowed to be operands in expressions other than array indexing
5039 // and structure member selection.
5040 if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType()))
5041 {
5042 switch (op)
5043 {
5044 case EOpIndexDirect:
5045 case EOpIndexIndirect:
5046 break;
jchen10b4cf5652017-05-05 18:51:17 +08005047
5048 default:
Nico Weberb5db2b42018-02-12 15:31:56 -05005049 ASSERT(op != EOpIndexDirectStruct);
jchen10b4cf5652017-05-05 18:51:17 +08005050 error(loc, "Invalid operation for variables with an opaque type",
5051 GetOperatorString(op));
5052 return false;
5053 }
5054 }
jchen10cc2a10e2017-05-03 14:05:12 +08005055
Jiajia Qinbc585152017-06-23 15:42:17 +08005056 if (right->getMemoryQualifier().writeonly)
5057 {
5058 error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op));
5059 return false;
5060 }
5061
5062 if (left->getMemoryQualifier().writeonly)
5063 {
5064 switch (op)
5065 {
5066 case EOpAssign:
5067 case EOpInitialize:
5068 case EOpIndexDirect:
5069 case EOpIndexIndirect:
5070 case EOpIndexDirectStruct:
5071 case EOpIndexDirectInterfaceBlock:
5072 break;
5073 default:
5074 error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op));
5075 return false;
5076 }
5077 }
5078
Olli Etuaho244be012016-08-18 15:26:02 +03005079 if (left->getType().getStruct() || right->getType().getStruct())
5080 {
5081 switch (op)
5082 {
5083 case EOpIndexDirectStruct:
5084 ASSERT(left->getType().getStruct());
5085 break;
5086 case EOpEqual:
5087 case EOpNotEqual:
5088 case EOpAssign:
5089 case EOpInitialize:
5090 if (left->getType() != right->getType())
5091 {
5092 return false;
5093 }
5094 break;
5095 default:
5096 error(loc, "Invalid operation for structs", GetOperatorString(op));
5097 return false;
5098 }
5099 }
5100
Olli Etuaho94050052017-05-08 14:17:44 +03005101 if (left->isInterfaceBlock() || right->isInterfaceBlock())
5102 {
5103 switch (op)
5104 {
5105 case EOpIndexDirectInterfaceBlock:
5106 ASSERT(left->getType().getInterfaceBlock());
5107 break;
5108 default:
5109 error(loc, "Invalid operation for interface blocks", GetOperatorString(op));
5110 return false;
5111 }
5112 }
5113
Kai Ninomiya57ea5332017-11-22 14:04:48 -08005114 if (left->isArray() != right->isArray())
Olli Etuahod6b14282015-03-17 14:31:35 +02005115 {
Kai Ninomiya57ea5332017-11-22 14:04:48 -08005116 error(loc, "array / non-array mismatch", GetOperatorString(op));
5117 return false;
5118 }
5119
5120 if (left->isArray())
5121 {
5122 ASSERT(right->isArray());
Jamie Madill6e06b1f2015-05-14 10:01:17 -04005123 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02005124 {
5125 error(loc, "Invalid operation for arrays", GetOperatorString(op));
5126 return false;
5127 }
5128
Olli Etuahoe79904c2015-03-18 16:56:42 +02005129 switch (op)
5130 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04005131 case EOpEqual:
5132 case EOpNotEqual:
5133 case EOpAssign:
5134 case EOpInitialize:
5135 break;
5136 default:
5137 error(loc, "Invalid operation for arrays", GetOperatorString(op));
5138 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02005139 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03005140 // At this point, size of implicitly sized arrays should be resolved.
Kai Ninomiya57ea5332017-11-22 14:04:48 -08005141 if (*left->getType().getArraySizes() != *right->getType().getArraySizes())
Olli Etuahoe79904c2015-03-18 16:56:42 +02005142 {
5143 error(loc, "array size mismatch", GetOperatorString(op));
5144 return false;
5145 }
Olli Etuahod6b14282015-03-17 14:31:35 +02005146 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02005147
5148 // Check ops which require integer / ivec parameters
5149 bool isBitShift = false;
5150 switch (op)
5151 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04005152 case EOpBitShiftLeft:
5153 case EOpBitShiftRight:
5154 case EOpBitShiftLeftAssign:
5155 case EOpBitShiftRightAssign:
5156 // Unsigned can be bit-shifted by signed and vice versa, but we need to
5157 // check that the basic type is an integer type.
5158 isBitShift = true;
5159 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
5160 {
5161 return false;
5162 }
5163 break;
5164 case EOpBitwiseAnd:
5165 case EOpBitwiseXor:
5166 case EOpBitwiseOr:
5167 case EOpBitwiseAndAssign:
5168 case EOpBitwiseXorAssign:
5169 case EOpBitwiseOrAssign:
5170 // It is enough to check the type of only one operand, since later it
5171 // is checked that the operand types match.
5172 if (!IsInteger(left->getBasicType()))
5173 {
5174 return false;
5175 }
5176 break;
5177 default:
5178 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02005179 }
5180
5181 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
5182 // So the basic type should usually match.
5183 if (!isBitShift && left->getBasicType() != right->getBasicType())
5184 {
5185 return false;
5186 }
5187
Olli Etuaho63e1ec52016-08-18 22:05:12 +03005188 // Check that:
5189 // 1. Type sizes match exactly on ops that require that.
5190 // 2. Restrictions for structs that contain arrays or samplers are respected.
5191 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
Jamie Madillb98c3a82015-07-23 14:26:04 -04005192 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02005193 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04005194 case EOpAssign:
5195 case EOpInitialize:
5196 case EOpEqual:
5197 case EOpNotEqual:
5198 // ESSL 1.00 sections 5.7, 5.8, 5.9
5199 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
5200 {
5201 error(loc, "undefined operation for structs containing arrays",
5202 GetOperatorString(op));
5203 return false;
5204 }
5205 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
5206 // we interpret the spec so that this extends to structs containing samplers,
5207 // similarly to ESSL 1.00 spec.
5208 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
5209 left->getType().isStructureContainingSamplers())
5210 {
5211 error(loc, "undefined operation for structs containing samplers",
5212 GetOperatorString(op));
5213 return false;
5214 }
Martin Radev2cc85b32016-08-05 16:22:53 +03005215
Olli Etuahoe1805592017-01-02 16:41:20 +00005216 if ((left->getNominalSize() != right->getNominalSize()) ||
5217 (left->getSecondarySize() != right->getSecondarySize()))
5218 {
5219 error(loc, "dimension mismatch", GetOperatorString(op));
5220 return false;
5221 }
5222 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04005223 case EOpLessThan:
5224 case EOpGreaterThan:
5225 case EOpLessThanEqual:
5226 case EOpGreaterThanEqual:
Olli Etuahoe1805592017-01-02 16:41:20 +00005227 if (!left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04005228 {
Olli Etuahoe1805592017-01-02 16:41:20 +00005229 error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
Jamie Madillb98c3a82015-07-23 14:26:04 -04005230 return false;
5231 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03005232 break;
5233 case EOpAdd:
5234 case EOpSub:
5235 case EOpDiv:
5236 case EOpIMod:
5237 case EOpBitShiftLeft:
5238 case EOpBitShiftRight:
5239 case EOpBitwiseAnd:
5240 case EOpBitwiseXor:
5241 case EOpBitwiseOr:
5242 case EOpAddAssign:
5243 case EOpSubAssign:
5244 case EOpDivAssign:
5245 case EOpIModAssign:
5246 case EOpBitShiftLeftAssign:
5247 case EOpBitShiftRightAssign:
5248 case EOpBitwiseAndAssign:
5249 case EOpBitwiseXorAssign:
5250 case EOpBitwiseOrAssign:
5251 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
5252 {
5253 return false;
5254 }
5255
5256 // Are the sizes compatible?
5257 if (left->getNominalSize() != right->getNominalSize() ||
5258 left->getSecondarySize() != right->getSecondarySize())
5259 {
5260 // If the nominal sizes of operands do not match:
5261 // One of them must be a scalar.
5262 if (!left->isScalar() && !right->isScalar())
5263 return false;
5264
5265 // In the case of compound assignment other than multiply-assign,
5266 // the right side needs to be a scalar. Otherwise a vector/matrix
5267 // would be assigned to a scalar. A scalar can't be shifted by a
5268 // vector either.
5269 if (!right->isScalar() &&
5270 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
5271 return false;
5272 }
5273 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04005274 default:
5275 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02005276 }
5277
Olli Etuahod6b14282015-03-17 14:31:35 +02005278 return true;
5279}
5280
Olli Etuaho1dded802016-08-18 18:13:13 +03005281bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
5282 const TType &left,
5283 const TType &right)
5284{
5285 switch (op)
5286 {
5287 case EOpMul:
5288 case EOpMulAssign:
5289 return left.getNominalSize() == right.getNominalSize() &&
5290 left.getSecondarySize() == right.getSecondarySize();
5291 case EOpVectorTimesScalar:
5292 return true;
5293 case EOpVectorTimesScalarAssign:
5294 ASSERT(!left.isMatrix() && !right.isMatrix());
5295 return left.isVector() && !right.isVector();
5296 case EOpVectorTimesMatrix:
5297 return left.getNominalSize() == right.getRows();
5298 case EOpVectorTimesMatrixAssign:
5299 ASSERT(!left.isMatrix() && right.isMatrix());
5300 return left.isVector() && left.getNominalSize() == right.getRows() &&
5301 left.getNominalSize() == right.getCols();
5302 case EOpMatrixTimesVector:
5303 return left.getCols() == right.getNominalSize();
5304 case EOpMatrixTimesScalar:
5305 return true;
5306 case EOpMatrixTimesScalarAssign:
5307 ASSERT(left.isMatrix() && !right.isMatrix());
5308 return !right.isVector();
5309 case EOpMatrixTimesMatrix:
5310 return left.getCols() == right.getRows();
5311 case EOpMatrixTimesMatrixAssign:
5312 ASSERT(left.isMatrix() && right.isMatrix());
5313 // We need to check two things:
5314 // 1. The matrix multiplication step is valid.
5315 // 2. The result will have the same number of columns as the lvalue.
5316 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
5317
5318 default:
5319 UNREACHABLE();
5320 return false;
5321 }
5322}
5323
Jamie Madillb98c3a82015-07-23 14:26:04 -04005324TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
5325 TIntermTyped *left,
5326 TIntermTyped *right,
5327 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02005328{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02005329 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02005330 return nullptr;
5331
Olli Etuahofc1806e2015-03-17 13:03:11 +02005332 switch (op)
5333 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04005334 case EOpEqual:
5335 case EOpNotEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04005336 case EOpLessThan:
5337 case EOpGreaterThan:
5338 case EOpLessThanEqual:
5339 case EOpGreaterThanEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04005340 break;
5341 case EOpLogicalOr:
5342 case EOpLogicalXor:
5343 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03005344 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
5345 !right->getType().getStruct());
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00005346 if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04005347 {
5348 return nullptr;
5349 }
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00005350 // Basic types matching should have been already checked.
5351 ASSERT(right->getBasicType() == EbtBool);
Jamie Madillb98c3a82015-07-23 14:26:04 -04005352 break;
5353 case EOpAdd:
5354 case EOpSub:
5355 case EOpDiv:
5356 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03005357 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
5358 !right->getType().getStruct());
5359 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04005360 {
5361 return nullptr;
5362 }
5363 break;
5364 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03005365 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
5366 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04005367 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03005368 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04005369 {
5370 return nullptr;
5371 }
5372 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04005373 default:
5374 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02005375 }
5376
Olli Etuaho1dded802016-08-18 18:13:13 +03005377 if (op == EOpMul)
5378 {
5379 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
5380 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
5381 {
5382 return nullptr;
5383 }
5384 }
5385
Olli Etuaho3fdec912016-08-18 15:08:06 +03005386 TIntermBinary *node = new TIntermBinary(op, left, right);
Olli Etuaho94bbed12018-03-20 14:44:53 +02005387 ASSERT(op != EOpAssign);
5388 markStaticReadIfSymbol(left);
5389 markStaticReadIfSymbol(right);
Olli Etuaho3fdec912016-08-18 15:08:06 +03005390 node->setLine(loc);
Olli Etuahoea22b7a2018-01-04 17:09:11 +02005391 return expressionOrFoldedResult(node);
Olli Etuahofc1806e2015-03-17 13:03:11 +02005392}
5393
Jamie Madillb98c3a82015-07-23 14:26:04 -04005394TIntermTyped *TParseContext::addBinaryMath(TOperator op,
5395 TIntermTyped *left,
5396 TIntermTyped *right,
5397 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02005398{
Olli Etuahofc1806e2015-03-17 13:03:11 +02005399 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02005400 if (node == 0)
5401 {
Olli Etuaho72e35892018-06-20 11:43:08 +03005402 binaryOpError(loc, GetOperatorString(op), left->getType(), right->getType());
Olli Etuaho09b22472015-02-11 11:47:26 +02005403 return left;
5404 }
5405 return node;
5406}
5407
Jamie Madillb98c3a82015-07-23 14:26:04 -04005408TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
5409 TIntermTyped *left,
5410 TIntermTyped *right,
5411 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02005412{
Olli Etuahofc1806e2015-03-17 13:03:11 +02005413 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho56229f12017-07-10 14:16:33 +03005414 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02005415 {
Olli Etuaho72e35892018-06-20 11:43:08 +03005416 binaryOpError(loc, GetOperatorString(op), left->getType(), right->getType());
Olli Etuaho3ec75682017-07-05 17:02:55 +03005417 node = CreateBoolNode(false);
Olli Etuaho56229f12017-07-10 14:16:33 +03005418 node->setLine(loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02005419 }
5420 return node;
5421}
5422
Jamie Madillb98c3a82015-07-23 14:26:04 -04005423TIntermTyped *TParseContext::addAssign(TOperator op,
5424 TIntermTyped *left,
5425 TIntermTyped *right,
5426 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02005427{
Olli Etuahocce89652017-06-19 16:04:09 +03005428 checkCanBeLValue(loc, "assign", left);
Olli Etuaho7b7d2e62018-03-23 16:37:36 +02005429 TIntermBinary *node = nullptr;
5430 if (binaryOpCommonCheck(op, left, right, loc))
5431 {
5432 if (op == EOpMulAssign)
5433 {
5434 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
5435 if (isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
5436 {
5437 node = new TIntermBinary(op, left, right);
5438 }
5439 }
5440 else
5441 {
5442 node = new TIntermBinary(op, left, right);
5443 }
5444 }
Olli Etuahod6b14282015-03-17 14:31:35 +02005445 if (node == nullptr)
5446 {
Olli Etuaho72e35892018-06-20 11:43:08 +03005447 assignError(loc, "assign", left->getType(), right->getType());
Olli Etuahod6b14282015-03-17 14:31:35 +02005448 return left;
5449 }
Olli Etuaho94bbed12018-03-20 14:44:53 +02005450 if (op != EOpAssign)
5451 {
5452 markStaticReadIfSymbol(left);
5453 }
5454 markStaticReadIfSymbol(right);
Olli Etuaho7b7d2e62018-03-23 16:37:36 +02005455 node->setLine(loc);
Olli Etuahod6b14282015-03-17 14:31:35 +02005456 return node;
5457}
5458
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02005459TIntermTyped *TParseContext::addComma(TIntermTyped *left,
5460 TIntermTyped *right,
5461 const TSourceLoc &loc)
5462{
Corentin Wallez0d959252016-07-12 17:26:32 -04005463 // WebGL2 section 5.26, the following results in an error:
5464 // "Sequence operator applied to void, arrays, or structs containing arrays"
Jamie Madilld7b1ab52016-12-12 14:42:19 -05005465 if (mShaderSpec == SH_WEBGL2_SPEC &&
5466 (left->isArray() || left->getBasicType() == EbtVoid ||
5467 left->getType().isStructureContainingArrays() || right->isArray() ||
5468 right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
Corentin Wallez0d959252016-07-12 17:26:32 -04005469 {
5470 error(loc,
5471 "sequence operator is not allowed for void, arrays, or structs containing arrays",
5472 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04005473 }
5474
Olli Etuaho0e99b7a2018-01-12 12:05:48 +02005475 TIntermBinary *commaNode = TIntermBinary::CreateComma(left, right, mShaderVersion);
Olli Etuaho94bbed12018-03-20 14:44:53 +02005476 markStaticReadIfSymbol(left);
5477 markStaticReadIfSymbol(right);
5478 commaNode->setLine(loc);
Olli Etuaho765924f2018-01-04 12:48:36 +02005479
5480 return expressionOrFoldedResult(commaNode);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02005481}
5482
Olli Etuaho49300862015-02-20 14:54:49 +02005483TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
5484{
5485 switch (op)
5486 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04005487 case EOpContinue:
5488 if (mLoopNestingLevel <= 0)
5489 {
5490 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04005491 }
5492 break;
5493 case EOpBreak:
5494 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
5495 {
5496 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04005497 }
5498 break;
5499 case EOpReturn:
5500 if (mCurrentFunctionType->getBasicType() != EbtVoid)
5501 {
5502 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04005503 }
5504 break;
Olli Etuahocce89652017-06-19 16:04:09 +03005505 case EOpKill:
5506 if (mShaderType != GL_FRAGMENT_SHADER)
5507 {
5508 error(loc, "discard supported in fragment shaders only", "discard");
5509 }
5510 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04005511 default:
Olli Etuahocce89652017-06-19 16:04:09 +03005512 UNREACHABLE();
Jamie Madillb98c3a82015-07-23 14:26:04 -04005513 break;
Olli Etuaho49300862015-02-20 14:54:49 +02005514 }
Olli Etuahocce89652017-06-19 16:04:09 +03005515 return addBranch(op, nullptr, loc);
Olli Etuaho49300862015-02-20 14:54:49 +02005516}
5517
Jamie Madillb98c3a82015-07-23 14:26:04 -04005518TIntermBranch *TParseContext::addBranch(TOperator op,
Olli Etuahocce89652017-06-19 16:04:09 +03005519 TIntermTyped *expression,
Jamie Madillb98c3a82015-07-23 14:26:04 -04005520 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02005521{
Olli Etuahocce89652017-06-19 16:04:09 +03005522 if (expression != nullptr)
Olli Etuaho49300862015-02-20 14:54:49 +02005523 {
Olli Etuaho94bbed12018-03-20 14:44:53 +02005524 markStaticReadIfSymbol(expression);
Olli Etuahocce89652017-06-19 16:04:09 +03005525 ASSERT(op == EOpReturn);
5526 mFunctionReturnsValue = true;
5527 if (mCurrentFunctionType->getBasicType() == EbtVoid)
5528 {
5529 error(loc, "void function cannot return a value", "return");
5530 }
5531 else if (*mCurrentFunctionType != expression->getType())
5532 {
5533 error(loc, "function return is not matching type:", "return");
5534 }
Olli Etuaho49300862015-02-20 14:54:49 +02005535 }
Olli Etuahocce89652017-06-19 16:04:09 +03005536 TIntermBranch *node = new TIntermBranch(op, expression);
5537 node->setLine(loc);
5538 return node;
Olli Etuaho49300862015-02-20 14:54:49 +02005539}
5540
Olli Etuaho94bbed12018-03-20 14:44:53 +02005541void TParseContext::appendStatement(TIntermBlock *block, TIntermNode *statement)
5542{
5543 if (statement != nullptr)
5544 {
5545 markStaticReadIfSymbol(statement);
5546 block->appendStatement(statement);
5547 }
5548}
5549
Martin Radev84aa2dc2017-09-11 15:51:02 +03005550void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
5551{
5552 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005553 const TFunction *func = functionCall->getFunction();
5554 if (BuiltInGroup::isTextureGather(func))
Martin Radev84aa2dc2017-09-11 15:51:02 +03005555 {
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005556 bool isTextureGatherOffset = BuiltInGroup::isTextureGatherOffset(func);
Martin Radev84aa2dc2017-09-11 15:51:02 +03005557 TIntermNode *componentNode = nullptr;
5558 TIntermSequence *arguments = functionCall->getSequence();
5559 ASSERT(arguments->size() >= 2u && arguments->size() <= 4u);
5560 const TIntermTyped *sampler = arguments->front()->getAsTyped();
5561 ASSERT(sampler != nullptr);
5562 switch (sampler->getBasicType())
5563 {
5564 case EbtSampler2D:
5565 case EbtISampler2D:
5566 case EbtUSampler2D:
5567 case EbtSampler2DArray:
5568 case EbtISampler2DArray:
5569 case EbtUSampler2DArray:
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005570 if ((!isTextureGatherOffset && arguments->size() == 3u) ||
Martin Radev84aa2dc2017-09-11 15:51:02 +03005571 (isTextureGatherOffset && arguments->size() == 4u))
5572 {
5573 componentNode = arguments->back();
5574 }
5575 break;
5576 case EbtSamplerCube:
5577 case EbtISamplerCube:
5578 case EbtUSamplerCube:
5579 ASSERT(!isTextureGatherOffset);
5580 if (arguments->size() == 3u)
5581 {
5582 componentNode = arguments->back();
5583 }
5584 break;
5585 case EbtSampler2DShadow:
5586 case EbtSampler2DArrayShadow:
5587 case EbtSamplerCubeShadow:
5588 break;
5589 default:
5590 UNREACHABLE();
5591 break;
5592 }
5593 if (componentNode)
5594 {
5595 const TIntermConstantUnion *componentConstantUnion =
5596 componentNode->getAsConstantUnion();
5597 if (componentNode->getAsTyped()->getQualifier() != EvqConst || !componentConstantUnion)
5598 {
5599 error(functionCall->getLine(), "Texture component must be a constant expression",
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005600 func->name());
Martin Radev84aa2dc2017-09-11 15:51:02 +03005601 }
5602 else
5603 {
5604 int component = componentConstantUnion->getIConst(0);
5605 if (component < 0 || component > 3)
5606 {
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005607 error(functionCall->getLine(), "Component must be in the range [0;3]",
5608 func->name());
Martin Radev84aa2dc2017-09-11 15:51:02 +03005609 }
5610 }
5611 }
5612 }
5613}
5614
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005615void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
5616{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08005617 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005618 const TFunction *func = functionCall->getFunction();
Jamie Madill50cf2be2018-06-15 09:46:57 -04005619 TIntermNode *offset = nullptr;
5620 TIntermSequence *arguments = functionCall->getSequence();
Martin Radev84aa2dc2017-09-11 15:51:02 +03005621 bool useTextureGatherOffsetConstraints = false;
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005622 if (BuiltInGroup::isTextureOffsetNoBias(func))
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005623 {
5624 offset = arguments->back();
5625 }
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005626 else if (BuiltInGroup::isTextureOffsetBias(func))
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005627 {
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005628 // A bias parameter follows the offset parameter.
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005629 ASSERT(arguments->size() >= 3);
5630 offset = (*arguments)[2];
5631 }
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005632 else if (BuiltInGroup::isTextureGatherOffset(func))
Martin Radev84aa2dc2017-09-11 15:51:02 +03005633 {
5634 ASSERT(arguments->size() >= 3u);
5635 const TIntermTyped *sampler = arguments->front()->getAsTyped();
5636 ASSERT(sampler != nullptr);
5637 switch (sampler->getBasicType())
5638 {
5639 case EbtSampler2D:
5640 case EbtISampler2D:
5641 case EbtUSampler2D:
5642 case EbtSampler2DArray:
5643 case EbtISampler2DArray:
5644 case EbtUSampler2DArray:
5645 offset = (*arguments)[2];
5646 break;
5647 case EbtSampler2DShadow:
5648 case EbtSampler2DArrayShadow:
5649 offset = (*arguments)[3];
5650 break;
5651 default:
5652 UNREACHABLE();
5653 break;
5654 }
5655 useTextureGatherOffsetConstraints = true;
5656 }
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005657 if (offset != nullptr)
5658 {
5659 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
5660 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
5661 {
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005662 error(functionCall->getLine(), "Texture offset must be a constant expression",
5663 func->name());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005664 }
5665 else
5666 {
5667 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
5668 size_t size = offsetConstantUnion->getType().getObjectSize();
Olli Etuahoea22b7a2018-01-04 17:09:11 +02005669 const TConstantUnion *values = offsetConstantUnion->getConstantValue();
Martin Radev84aa2dc2017-09-11 15:51:02 +03005670 int minOffsetValue = useTextureGatherOffsetConstraints ? mMinProgramTextureGatherOffset
5671 : mMinProgramTexelOffset;
5672 int maxOffsetValue = useTextureGatherOffsetConstraints ? mMaxProgramTextureGatherOffset
5673 : mMaxProgramTexelOffset;
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005674 for (size_t i = 0u; i < size; ++i)
5675 {
5676 int offsetValue = values[i].getIConst();
Martin Radev84aa2dc2017-09-11 15:51:02 +03005677 if (offsetValue > maxOffsetValue || offsetValue < minOffsetValue)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005678 {
Jonah Ryan-Davisf563fdc2019-01-31 13:53:59 -05005679 std::stringstream tokenStream = sh::InitializeStream<std::stringstream>();
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005680 tokenStream << offsetValue;
5681 std::string token = tokenStream.str();
5682 error(offset->getLine(), "Texture offset value out of valid range",
5683 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02005684 }
5685 }
5686 }
5687 }
5688}
5689
Jiajia Qina3106c52017-11-03 09:39:39 +08005690void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall)
5691{
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005692 const TFunction *func = functionCall->getFunction();
5693 if (BuiltInGroup::isAtomicMemory(func))
Jiajia Qina3106c52017-11-03 09:39:39 +08005694 {
Jiawei Shaoa6a78422018-06-28 08:32:54 +08005695 ASSERT(IsAtomicFunction(functionCall->getOp()));
Jiajia Qina3106c52017-11-03 09:39:39 +08005696 TIntermSequence *arguments = functionCall->getSequence();
5697 TIntermTyped *memNode = (*arguments)[0]->getAsTyped();
5698
5699 if (IsBufferOrSharedVariable(memNode))
5700 {
5701 return;
5702 }
5703
5704 while (memNode->getAsBinaryNode())
5705 {
5706 memNode = memNode->getAsBinaryNode()->getLeft();
5707 if (IsBufferOrSharedVariable(memNode))
5708 {
5709 return;
5710 }
5711 }
5712
5713 error(memNode->getLine(),
5714 "The value passed to the mem argument of an atomic memory function does not "
5715 "correspond to a buffer or shared variable.",
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005716 func->name());
Jiajia Qina3106c52017-11-03 09:39:39 +08005717 }
5718}
5719
Martin Radev2cc85b32016-08-05 16:22:53 +03005720// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
5721void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
5722{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08005723 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Martin Radev2cc85b32016-08-05 16:22:53 +03005724
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005725 const TFunction *func = functionCall->getFunction();
5726
5727 if (BuiltInGroup::isImage(func))
Martin Radev2cc85b32016-08-05 16:22:53 +03005728 {
5729 TIntermSequence *arguments = functionCall->getSequence();
Olli Etuaho485eefd2017-02-14 17:40:06 +00005730 TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
Martin Radev2cc85b32016-08-05 16:22:53 +03005731
Olli Etuaho485eefd2017-02-14 17:40:06 +00005732 const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
Martin Radev2cc85b32016-08-05 16:22:53 +03005733
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005734 if (BuiltInGroup::isImageStore(func))
Martin Radev2cc85b32016-08-05 16:22:53 +03005735 {
5736 if (memoryQualifier.readonly)
5737 {
5738 error(imageNode->getLine(),
5739 "'imageStore' cannot be used with images qualified as 'readonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005740 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03005741 }
5742 }
Olli Etuaho2bfe9f62018-03-02 16:53:29 +02005743 else if (BuiltInGroup::isImageLoad(func))
Martin Radev2cc85b32016-08-05 16:22:53 +03005744 {
5745 if (memoryQualifier.writeonly)
5746 {
5747 error(imageNode->getLine(),
5748 "'imageLoad' cannot be used with images qualified as 'writeonly'",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005749 GetImageArgumentToken(imageNode));
Martin Radev2cc85b32016-08-05 16:22:53 +03005750 }
5751 }
5752 }
5753}
5754
5755// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
5756void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
5757 const TFunction *functionDefinition,
5758 const TIntermAggregate *functionCall)
5759{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08005760 ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
Martin Radev2cc85b32016-08-05 16:22:53 +03005761
5762 const TIntermSequence &arguments = *functionCall->getSequence();
5763
5764 ASSERT(functionDefinition->getParamCount() == arguments.size());
5765
5766 for (size_t i = 0; i < arguments.size(); ++i)
5767 {
Olli Etuaho485eefd2017-02-14 17:40:06 +00005768 TIntermTyped *typedArgument = arguments[i]->getAsTyped();
5769 const TType &functionArgumentType = typedArgument->getType();
Olli Etuahod4bd9632018-03-08 16:32:44 +02005770 const TType &functionParameterType = functionDefinition->getParam(i)->getType();
Martin Radev2cc85b32016-08-05 16:22:53 +03005771 ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
5772
5773 if (IsImage(functionArgumentType.getBasicType()))
5774 {
5775 const TMemoryQualifier &functionArgumentMemoryQualifier =
5776 functionArgumentType.getMemoryQualifier();
5777 const TMemoryQualifier &functionParameterMemoryQualifier =
5778 functionParameterType.getMemoryQualifier();
5779 if (functionArgumentMemoryQualifier.readonly &&
5780 !functionParameterMemoryQualifier.readonly)
5781 {
5782 error(functionCall->getLine(),
5783 "Function call discards the 'readonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005784 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03005785 }
5786
5787 if (functionArgumentMemoryQualifier.writeonly &&
5788 !functionParameterMemoryQualifier.writeonly)
5789 {
5790 error(functionCall->getLine(),
5791 "Function call discards the 'writeonly' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005792 GetImageArgumentToken(typedArgument));
Martin Radev2cc85b32016-08-05 16:22:53 +03005793 }
Martin Radev049edfa2016-11-11 14:35:37 +02005794
5795 if (functionArgumentMemoryQualifier.coherent &&
5796 !functionParameterMemoryQualifier.coherent)
5797 {
5798 error(functionCall->getLine(),
5799 "Function call discards the 'coherent' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005800 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02005801 }
5802
5803 if (functionArgumentMemoryQualifier.volatileQualifier &&
5804 !functionParameterMemoryQualifier.volatileQualifier)
5805 {
5806 error(functionCall->getLine(),
5807 "Function call discards the 'volatile' qualifier from image",
Olli Etuaho485eefd2017-02-14 17:40:06 +00005808 GetImageArgumentToken(typedArgument));
Martin Radev049edfa2016-11-11 14:35:37 +02005809 }
Martin Radev2cc85b32016-08-05 16:22:53 +03005810 }
5811 }
5812}
5813
Olli Etuaho95ed1942018-02-01 14:01:19 +02005814TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunctionLookup *fnCall, const TSourceLoc &loc)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005815{
Olli Etuaho95ed1942018-02-01 14:01:19 +02005816 if (fnCall->thisNode() != nullptr)
5817 {
5818 return addMethod(fnCall, loc);
5819 }
5820 if (fnCall->isConstructor())
5821 {
5822 return addConstructor(fnCall, loc);
5823 }
5824 return addNonConstructorFunctionCall(fnCall, loc);
Olli Etuaho72d10202017-01-19 15:58:30 +00005825}
5826
Olli Etuaho95ed1942018-02-01 14:01:19 +02005827TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc)
Olli Etuaho72d10202017-01-19 15:58:30 +00005828{
Olli Etuaho95ed1942018-02-01 14:01:19 +02005829 TIntermTyped *thisNode = fnCall->thisNode();
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005830 // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
5831 // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
5832 // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
Olli Etuahoae4dbf32017-12-08 20:49:00 +01005833 // So accessing fnCall->name() below is safe.
Olli Etuaho95ed1942018-02-01 14:01:19 +02005834 if (fnCall->name() != "length")
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005835 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02005836 error(loc, "invalid method", fnCall->name());
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005837 }
Olli Etuaho95ed1942018-02-01 14:01:19 +02005838 else if (!fnCall->arguments().empty())
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005839 {
5840 error(loc, "method takes no parameters", "length");
5841 }
Olli Etuaho95ed1942018-02-01 14:01:19 +02005842 else if (!thisNode->isArray())
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005843 {
5844 error(loc, "length can only be called on arrays", "length");
5845 }
Olli Etuaho95ed1942018-02-01 14:01:19 +02005846 else if (thisNode->getQualifier() == EvqPerVertexIn &&
Jiawei Shaod8105a02017-08-08 09:54:36 +08005847 mGeometryShaderInputPrimitiveType == EptUndefined)
5848 {
Jiawei Shaobd924af2017-11-16 15:28:04 +08005849 ASSERT(mShaderType == GL_GEOMETRY_SHADER_EXT);
Jiawei Shaod8105a02017-08-08 09:54:36 +08005850 error(loc, "missing input primitive declaration before calling length on gl_in", "length");
5851 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005852 else
5853 {
Olli Etuaho5fec7ab2018-04-04 11:58:33 +03005854 TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode, nullptr);
Qin Jiajia19f2f9e2018-12-07 15:10:48 +08005855 markStaticReadIfSymbol(thisNode);
Olli Etuahobb2bbfb2017-08-24 15:43:33 +03005856 node->setLine(loc);
5857 return node->fold(mDiagnostics);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005858 }
Olli Etuahobb2bbfb2017-08-24 15:43:33 +03005859 return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst));
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005860}
5861
Olli Etuaho95ed1942018-02-01 14:01:19 +02005862TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCall,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005863 const TSourceLoc &loc)
5864{
Olli Etuaho697bf652018-02-16 11:50:54 +02005865 // First check whether the function has been hidden by a variable name or struct typename by
5866 // using the symbol looked up in the lexical phase. If the function is not hidden, look for one
5867 // with a matching argument list.
5868 if (fnCall->symbol() != nullptr && !fnCall->symbol()->isFunction())
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005869 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02005870 error(loc, "function name expected", fnCall->name());
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005871 }
5872 else
5873 {
Olli Etuahoe80825e2018-02-16 10:24:53 +02005874 // There are no inner functions, so it's enough to look for user-defined functions in the
5875 // global scope.
Olli Etuaho697bf652018-02-16 11:50:54 +02005876 const TSymbol *symbol = symbolTable.findGlobal(fnCall->getMangledName());
Olli Etuahoe80825e2018-02-16 10:24:53 +02005877 if (symbol != nullptr)
5878 {
5879 // A user-defined function - could be an overloaded built-in as well.
5880 ASSERT(symbol->symbolType() == SymbolType::UserDefined);
5881 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
5882 TIntermAggregate *callNode =
5883 TIntermAggregate::CreateFunctionCall(*fnCandidate, &fnCall->arguments());
5884 callNode->setLine(loc);
5885 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
5886 functionCallRValueLValueErrorCheck(fnCandidate, callNode);
5887 return callNode;
5888 }
5889
5890 symbol = symbolTable.findBuiltIn(fnCall->getMangledName(), mShaderVersion);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005891 if (symbol == nullptr)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005892 {
Olli Etuahofbb1c792018-01-19 16:26:59 +02005893 error(loc, "no matching overloaded function found", fnCall->name());
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005894 }
5895 else
5896 {
Olli Etuahoe80825e2018-02-16 10:24:53 +02005897 // A built-in function.
5898 ASSERT(symbol->symbolType() == SymbolType::BuiltIn);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005899 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
Olli Etuahoe80825e2018-02-16 10:24:53 +02005900
Olli Etuaho37b697e2018-01-29 12:19:27 +02005901 if (fnCandidate->extension() != TExtension::UNDEFINED)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005902 {
Olli Etuaho54a29ff2017-11-28 17:35:20 +02005903 checkCanUseExtension(loc, fnCandidate->extension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005904 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005905 TOperator op = fnCandidate->getBuiltInOp();
Olli Etuahoe80825e2018-02-16 10:24:53 +02005906 if (op != EOpCallBuiltInFunction)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005907 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005908 // A function call mapped to a built-in operation.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005909 if (fnCandidate->getParamCount() == 1)
5910 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005911 // Treat it like a built-in unary operator.
Olli Etuaho95ed1942018-02-01 14:01:19 +02005912 TIntermNode *unaryParamNode = fnCall->arguments().front();
Olli Etuaho5fec7ab2018-04-04 11:58:33 +03005913 TIntermTyped *callNode =
5914 createUnaryMath(op, unaryParamNode->getAsTyped(), loc, fnCandidate);
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08005915 ASSERT(callNode != nullptr);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005916 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005917 }
Jiawei Shaoa6a78422018-06-28 08:32:54 +08005918
Olli Etuahoe80825e2018-02-16 10:24:53 +02005919 TIntermAggregate *callNode =
5920 TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, &fnCall->arguments());
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005921 callNode->setLine(loc);
5922
Jiawei Shaoa6a78422018-06-28 08:32:54 +08005923 checkAtomicMemoryBuiltinFunctions(callNode);
5924
Olli Etuahoe80825e2018-02-16 10:24:53 +02005925 // Some built-in functions have out parameters too.
5926 functionCallRValueLValueErrorCheck(fnCandidate, callNode);
5927
5928 // See if we can constant fold a built-in. Note that this may be possible
5929 // even if it is not const-qualified.
5930 return callNode->fold(mDiagnostics);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005931 }
Olli Etuahoe80825e2018-02-16 10:24:53 +02005932
5933 // This is a built-in function with no op associated with it.
5934 TIntermAggregate *callNode =
5935 TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, &fnCall->arguments());
5936 callNode->setLine(loc);
5937 checkTextureOffsetConst(callNode);
5938 checkTextureGather(callNode);
5939 checkImageMemoryAccessForBuiltinFunctions(callNode);
Olli Etuahoe80825e2018-02-16 10:24:53 +02005940 functionCallRValueLValueErrorCheck(fnCandidate, callNode);
5941 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005942 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005943 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08005944
5945 // Error message was already written. Put on a dummy node for error recovery.
Olli Etuaho3ec75682017-07-05 17:02:55 +03005946 return CreateZeroNode(TType(EbtFloat, EbpMedium, EvqConst));
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02005947}
5948
Jamie Madillb98c3a82015-07-23 14:26:04 -04005949TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005950 TIntermTyped *trueExpression,
5951 TIntermTyped *falseExpression,
Olli Etuaho52901742015-04-15 13:42:45 +03005952 const TSourceLoc &loc)
5953{
Olli Etuaho56229f12017-07-10 14:16:33 +03005954 if (!checkIsScalarBool(loc, cond))
5955 {
5956 return falseExpression;
5957 }
Olli Etuaho52901742015-04-15 13:42:45 +03005958
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005959 if (trueExpression->getType() != falseExpression->getType())
Olli Etuaho52901742015-04-15 13:42:45 +03005960 {
Olli Etuaho72e35892018-06-20 11:43:08 +03005961 TInfoSinkBase reasonStream;
5962 reasonStream << "mismatching ternary operator operand types '" << trueExpression->getType()
5963 << " and '" << falseExpression->getType() << "'";
5964 error(loc, reasonStream.c_str(), "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005965 return falseExpression;
Olli Etuaho52901742015-04-15 13:42:45 +03005966 }
Olli Etuahode318b22016-10-25 16:18:25 +01005967 if (IsOpaqueType(trueExpression->getBasicType()))
5968 {
5969 // ESSL 1.00 section 4.1.7
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005970 // ESSL 3.00.6 section 4.1.7
Olli Etuahode318b22016-10-25 16:18:25 +01005971 // Opaque/sampler types are not allowed in most types of expressions, including ternary.
5972 // Note that structs containing opaque types don't need to be checked as structs are
5973 // forbidden below.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005974 error(loc, "ternary operator is not allowed for opaque types", "?:");
Olli Etuahode318b22016-10-25 16:18:25 +01005975 return falseExpression;
5976 }
5977
Jiajia Qinbc585152017-06-23 15:42:17 +08005978 if (cond->getMemoryQualifier().writeonly || trueExpression->getMemoryQualifier().writeonly ||
5979 falseExpression->getMemoryQualifier().writeonly)
5980 {
5981 error(loc, "ternary operator is not allowed for variables with writeonly", "?:");
5982 return falseExpression;
5983 }
5984
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005985 // ESSL 1.00.17 sections 5.2 and 5.7:
Olli Etuahoa2d53032015-04-15 14:14:44 +03005986 // Ternary operator is not among the operators allowed for structures/arrays.
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005987 // ESSL 3.00.6 section 5.7:
5988 // Ternary operator support is optional for arrays. No certainty that it works across all
5989 // devices with struct either, so we err on the side of caution here. TODO (oetuaho@nvidia.com):
5990 // Would be nice to make the spec and implementation agree completely here.
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005991 if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
Olli Etuahoa2d53032015-04-15 14:14:44 +03005992 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005993 error(loc, "ternary operator is not allowed for structures or arrays", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03005994 return falseExpression;
Olli Etuahoa2d53032015-04-15 14:14:44 +03005995 }
Olli Etuaho94050052017-05-08 14:17:44 +03005996 if (trueExpression->getBasicType() == EbtInterfaceBlock)
5997 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03005998 error(loc, "ternary operator is not allowed for interface blocks", "?:");
Olli Etuaho94050052017-05-08 14:17:44 +03005999 return falseExpression;
6000 }
6001
Corentin Wallez0d959252016-07-12 17:26:32 -04006002 // WebGL2 section 5.26, the following results in an error:
6003 // "Ternary operator applied to void, arrays, or structs containing arrays"
Olli Etuahod0bad2c2016-09-09 18:01:16 +03006004 if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
Corentin Wallez0d959252016-07-12 17:26:32 -04006005 {
Olli Etuahoe01c02b2017-05-08 14:41:49 +03006006 error(loc, "ternary operator is not allowed for void", "?:");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03006007 return falseExpression;
Corentin Wallez0d959252016-07-12 17:26:32 -04006008 }
6009
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03006010 TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression);
Olli Etuaho94bbed12018-03-20 14:44:53 +02006011 markStaticReadIfSymbol(cond);
6012 markStaticReadIfSymbol(trueExpression);
6013 markStaticReadIfSymbol(falseExpression);
Olli Etuahoeb7f90f2017-07-07 17:25:23 +03006014 node->setLine(loc);
Olli Etuaho765924f2018-01-04 12:48:36 +02006015 return expressionOrFoldedResult(node);
Olli Etuaho52901742015-04-15 13:42:45 +03006016}
Olli Etuaho49300862015-02-20 14:54:49 +02006017
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00006018//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00006019// Parse an array of strings using yyparse.
6020//
6021// Returns 0 for success.
6022//
Jamie Madillb98c3a82015-07-23 14:26:04 -04006023int PaParseStrings(size_t count,
6024 const char *const string[],
6025 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05306026 TParseContext *context)
6027{
Yunchao He4f285442017-04-21 12:15:49 +08006028 if ((count == 0) || (string == nullptr))
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00006029 return 1;
6030
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00006031 if (glslang_initialize(context))
6032 return 1;
6033
alokp@chromium.org408c45e2012-04-05 15:54:43 +00006034 int error = glslang_scan(count, string, length, context);
6035 if (!error)
6036 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00006037
alokp@chromium.org73bc2982012-06-19 18:48:05 +00006038 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00006039
alokp@chromium.org6b495712012-06-29 00:06:58 +00006040 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00006041}
Jamie Madill45bcc782016-11-07 13:58:48 -05006042
6043} // namespace sh