blob: d807ea8a446baae21a65deedb90128e55c6f94e1 [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
daniel@transgaming.comb401a922012-10-26 18:58:24 +000012#include "compiler/preprocessor/SourceLocation.h"
Dmitry Skiba01971112015-07-10 14:54:00 -040013#include "compiler/translator/Cache.h"
Olli Etuahoac5274d2015-02-20 10:19:08 +020014#include "compiler/translator/glslang.h"
15#include "compiler/translator/ValidateSwitch.h"
Olli Etuahob0c645e2015-05-12 14:25:36 +030016#include "compiler/translator/ValidateGlobalInitializer.h"
Olli Etuaho37ad4742015-04-27 13:18:50 +030017#include "compiler/translator/util.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000018
Jamie Madill45bcc782016-11-07 13:58:48 -050019namespace sh
20{
21
alokp@chromium.org8b851c62012-06-15 16:25:11 +000022///////////////////////////////////////////////////////////////////////
23//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000024// Sub- vector and matrix fields
25//
26////////////////////////////////////////////////////////////////////////
27
Martin Radev2cc85b32016-08-05 16:22:53 +030028namespace
29{
30
31const int kWebGLMaxStructNesting = 4;
32
33bool ContainsSampler(const TType &type)
34{
35 if (IsSampler(type.getBasicType()))
36 return true;
37
38 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock())
39 {
40 const TFieldList &fields = type.getStruct()->fields();
41 for (unsigned int i = 0; i < fields.size(); ++i)
42 {
43 if (ContainsSampler(*fields[i]->type()))
44 return true;
45 }
46 }
47
48 return false;
49}
50
51bool ContainsImage(const TType &type)
52{
53 if (IsImage(type.getBasicType()))
54 return true;
55
56 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock())
57 {
58 const TFieldList &fields = type.getStruct()->fields();
59 for (unsigned int i = 0; i < fields.size(); ++i)
60 {
61 if (ContainsImage(*fields[i]->type()))
62 return true;
63 }
64 }
65
66 return false;
67}
68
69} // namespace
70
Jamie Madillacb4b812016-11-07 13:50:29 -050071TParseContext::TParseContext(TSymbolTable &symt,
72 TExtensionBehavior &ext,
73 sh::GLenum type,
74 ShShaderSpec spec,
75 ShCompileOptions options,
76 bool checksPrecErrors,
Olli Etuaho77ba4082016-12-16 12:01:18 +000077 TDiagnostics *diagnostics,
Jamie Madillacb4b812016-11-07 13:50:29 -050078 const ShBuiltInResources &resources)
79 : intermediate(),
80 symbolTable(symt),
81 mDeferredSingleDeclarationErrorCheck(false),
82 mShaderType(type),
83 mShaderSpec(spec),
84 mCompileOptions(options),
85 mShaderVersion(100),
86 mTreeRoot(nullptr),
87 mLoopNestingLevel(0),
88 mStructNestingLevel(0),
89 mSwitchNestingLevel(0),
90 mCurrentFunctionType(nullptr),
91 mFunctionReturnsValue(false),
92 mChecksPrecisionErrors(checksPrecErrors),
93 mFragmentPrecisionHighOnESSL1(false),
94 mDefaultMatrixPacking(EmpColumnMajor),
95 mDefaultBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
Olli Etuaho77ba4082016-12-16 12:01:18 +000096 mDiagnostics(diagnostics),
Jamie Madillacb4b812016-11-07 13:50:29 -050097 mDirectiveHandler(ext,
Olli Etuaho77ba4082016-12-16 12:01:18 +000098 *mDiagnostics,
Jamie Madillacb4b812016-11-07 13:50:29 -050099 mShaderVersion,
100 mShaderType,
101 resources.WEBGL_debug_shader_precision == 1),
Olli Etuaho77ba4082016-12-16 12:01:18 +0000102 mPreprocessor(mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()),
Jamie Madillacb4b812016-11-07 13:50:29 -0500103 mScanner(nullptr),
104 mUsesFragData(false),
105 mUsesFragColor(false),
106 mUsesSecondaryOutputs(false),
107 mMinProgramTexelOffset(resources.MinProgramTexelOffset),
108 mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
Olli Etuaho09b04a22016-12-15 13:30:26 +0000109 mMultiviewAvailable(resources.OVR_multiview == 1),
Jamie Madillacb4b812016-11-07 13:50:29 -0500110 mComputeShaderLocalSizeDeclared(false),
Olli Etuaho09b04a22016-12-15 13:30:26 +0000111 mNumViews(-1),
112 mMaxNumViews(resources.MaxViewsOVR),
Jamie Madillacb4b812016-11-07 13:50:29 -0500113 mDeclaringFunction(false)
114{
115 mComputeShaderLocalSize.fill(-1);
116}
117
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000118//
119// Look at a '.' field selector string and change it into offsets
120// for a vector.
121//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400122bool TParseContext::parseVectorFields(const TString &compString,
123 int vecSize,
124 TVectorFields &fields,
Arun Patole7e7e68d2015-05-22 12:02:25 +0530125 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000126{
Jamie Madillb98c3a82015-07-23 14:26:04 -0400127 fields.num = (int)compString.size();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530128 if (fields.num > 4)
129 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000130 error(line, "illegal vector field selection", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000131 return false;
132 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133
Jamie Madillb98c3a82015-07-23 14:26:04 -0400134 enum
135 {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000136 exyzw,
137 ergba,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000138 estpq
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000139 } fieldSet[4];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000140
Arun Patole7e7e68d2015-05-22 12:02:25 +0530141 for (int i = 0; i < fields.num; ++i)
142 {
143 switch (compString[i])
144 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400145 case 'x':
146 fields.offsets[i] = 0;
147 fieldSet[i] = exyzw;
148 break;
149 case 'r':
150 fields.offsets[i] = 0;
151 fieldSet[i] = ergba;
152 break;
153 case 's':
154 fields.offsets[i] = 0;
155 fieldSet[i] = estpq;
156 break;
157 case 'y':
158 fields.offsets[i] = 1;
159 fieldSet[i] = exyzw;
160 break;
161 case 'g':
162 fields.offsets[i] = 1;
163 fieldSet[i] = ergba;
164 break;
165 case 't':
166 fields.offsets[i] = 1;
167 fieldSet[i] = estpq;
168 break;
169 case 'z':
170 fields.offsets[i] = 2;
171 fieldSet[i] = exyzw;
172 break;
173 case 'b':
174 fields.offsets[i] = 2;
175 fieldSet[i] = ergba;
176 break;
177 case 'p':
178 fields.offsets[i] = 2;
179 fieldSet[i] = estpq;
180 break;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530181
Jamie Madillb98c3a82015-07-23 14:26:04 -0400182 case 'w':
183 fields.offsets[i] = 3;
184 fieldSet[i] = exyzw;
185 break;
186 case 'a':
187 fields.offsets[i] = 3;
188 fieldSet[i] = ergba;
189 break;
190 case 'q':
191 fields.offsets[i] = 3;
192 fieldSet[i] = estpq;
193 break;
194 default:
195 error(line, "illegal vector field selection", compString.c_str());
196 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000197 }
198 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000199
Arun Patole7e7e68d2015-05-22 12:02:25 +0530200 for (int i = 0; i < fields.num; ++i)
201 {
202 if (fields.offsets[i] >= vecSize)
203 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400204 error(line, "vector field selection out of range", compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000205 return false;
206 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000207
Arun Patole7e7e68d2015-05-22 12:02:25 +0530208 if (i > 0)
209 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400210 if (fieldSet[i] != fieldSet[i - 1])
Arun Patole7e7e68d2015-05-22 12:02:25 +0530211 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400212 error(line, "illegal - vector component fields not from the same set",
213 compString.c_str());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000214 return false;
215 }
216 }
217 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000218
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000219 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000220}
221
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222///////////////////////////////////////////////////////////////////////
223//
224// Errors
225//
226////////////////////////////////////////////////////////////////////////
227
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000228//
229// Used by flex/bison to output all syntax and parsing errors.
230//
Olli Etuaho4de340a2016-12-16 09:32:03 +0000231void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000232{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000233 mDiagnostics->error(loc, reason, token);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000234}
235
Olli Etuaho4de340a2016-12-16 09:32:03 +0000236void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530237{
Olli Etuaho77ba4082016-12-16 12:01:18 +0000238 mDiagnostics->warning(loc, reason, token);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +0000239}
240
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200241void TParseContext::outOfRangeError(bool isError,
242 const TSourceLoc &loc,
243 const char *reason,
Olli Etuaho4de340a2016-12-16 09:32:03 +0000244 const char *token)
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200245{
246 if (isError)
247 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000248 error(loc, reason, token);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200249 }
250 else
251 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000252 warning(loc, reason, token);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200253 }
254}
255
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256//
257// Same error message for all places assignments don't work.
258//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530259void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000261 std::stringstream reasonStream;
262 reasonStream << "cannot convert from '" << right << "' to '" << left << "'";
263 std::string reason = reasonStream.str();
264 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265}
266
267//
268// Same error message for all places unary operations don't work.
269//
Arun Patole7e7e68d2015-05-22 12:02:25 +0530270void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000271{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000272 std::stringstream reasonStream;
273 reasonStream << "wrong operand type - no operation '" << op
274 << "' exists that takes an operand of type " << operand
275 << " (or there is no acceptable conversion)";
276 std::string reason = reasonStream.str();
277 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000278}
279
280//
281// Same error message for all binary operations don't work.
282//
Jamie Madillb98c3a82015-07-23 14:26:04 -0400283void TParseContext::binaryOpError(const TSourceLoc &line,
284 const char *op,
285 TString left,
286 TString right)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000287{
Olli Etuaho4de340a2016-12-16 09:32:03 +0000288 std::stringstream reasonStream;
289 reasonStream << "wrong operand types - no operation '" << op
290 << "' exists that takes a left-hand operand of type '" << left
291 << "' and a right operand of type '" << right
292 << "' (or there is no acceptable conversion)";
293 std::string reason = reasonStream.str();
294 error(line, reason.c_str(), op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000295}
296
Olli Etuaho856c4972016-08-08 11:38:39 +0300297void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
298 TPrecision precision,
299 TBasicType type)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530300{
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400301 if (!mChecksPrecisionErrors)
Olli Etuaho383b7912016-08-05 11:22:59 +0300302 return;
Martin Radev70866b82016-07-22 15:27:42 +0300303
304 if (precision != EbpUndefined && !SupportsPrecision(type))
305 {
306 error(line, "illegal type for precision qualifier", getBasicString(type));
307 }
308
Olli Etuaho183d7e22015-11-20 15:59:09 +0200309 if (precision == EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530310 {
Olli Etuaho183d7e22015-11-20 15:59:09 +0200311 switch (type)
312 {
313 case EbtFloat:
Jamie Madillb98c3a82015-07-23 14:26:04 -0400314 error(line, "No precision specified for (float)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300315 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200316 case EbtInt:
317 case EbtUInt:
318 UNREACHABLE(); // there's always a predeclared qualifier
Jamie Madillb98c3a82015-07-23 14:26:04 -0400319 error(line, "No precision specified (int)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300320 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200321 default:
322 if (IsSampler(type))
323 {
324 error(line, "No precision specified (sampler)", "");
Olli Etuaho383b7912016-08-05 11:22:59 +0300325 return;
Olli Etuaho183d7e22015-11-20 15:59:09 +0200326 }
Martin Radev2cc85b32016-08-05 16:22:53 +0300327 if (IsImage(type))
328 {
329 error(line, "No precision specified (image)", "");
330 return;
331 }
Olli Etuaho183d7e22015-11-20 15:59:09 +0200332 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000333 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000334}
335
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000336// Both test and if necessary, spit out an error, to see if the node is really
337// an l-value that can be operated on this way.
Olli Etuaho856c4972016-08-08 11:38:39 +0300338bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500340 TIntermSymbol *symNode = node->getAsSymbolNode();
341 TIntermBinary *binaryNode = node->getAsBinaryNode();
Olli Etuahob6fa0432016-09-28 16:28:05 +0100342 TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
343
344 if (swizzleNode)
345 {
346 bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
347 if (ok && swizzleNode->hasDuplicateOffsets())
348 {
349 error(line, " l-value of swizzle cannot have duplicate components", op);
350 return false;
351 }
352 return ok;
353 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000354
Arun Patole7e7e68d2015-05-22 12:02:25 +0530355 if (binaryNode)
356 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400357 switch (binaryNode->getOp())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530358 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400359 case EOpIndexDirect:
360 case EOpIndexIndirect:
361 case EOpIndexDirectStruct:
362 case EOpIndexDirectInterfaceBlock:
Olli Etuaho856c4972016-08-08 11:38:39 +0300363 return checkCanBeLValue(line, op, binaryNode->getLeft());
Jamie Madillb98c3a82015-07-23 14:26:04 -0400364 default:
365 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000366 }
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000367 error(line, " l-value required", op);
Olli Etuaho8a176262016-08-16 14:23:01 +0300368 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000369 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000370
Arun Patole7e7e68d2015-05-22 12:02:25 +0530371 const char *message = 0;
372 switch (node->getQualifier())
373 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400374 case EvqConst:
375 message = "can't modify a const";
376 break;
377 case EvqConstReadOnly:
378 message = "can't modify a const";
379 break;
380 case EvqAttribute:
381 message = "can't modify an attribute";
382 break;
383 case EvqFragmentIn:
384 message = "can't modify an input";
385 break;
386 case EvqVertexIn:
387 message = "can't modify an input";
388 break;
389 case EvqUniform:
390 message = "can't modify a uniform";
391 break;
392 case EvqVaryingIn:
393 message = "can't modify a varying";
394 break;
395 case EvqFragCoord:
396 message = "can't modify gl_FragCoord";
397 break;
398 case EvqFrontFacing:
399 message = "can't modify gl_FrontFacing";
400 break;
401 case EvqPointCoord:
402 message = "can't modify gl_PointCoord";
403 break;
Martin Radevb0883602016-08-04 17:48:58 +0300404 case EvqNumWorkGroups:
405 message = "can't modify gl_NumWorkGroups";
406 break;
407 case EvqWorkGroupSize:
408 message = "can't modify gl_WorkGroupSize";
409 break;
410 case EvqWorkGroupID:
411 message = "can't modify gl_WorkGroupID";
412 break;
413 case EvqLocalInvocationID:
414 message = "can't modify gl_LocalInvocationID";
415 break;
416 case EvqGlobalInvocationID:
417 message = "can't modify gl_GlobalInvocationID";
418 break;
419 case EvqLocalInvocationIndex:
420 message = "can't modify gl_LocalInvocationIndex";
421 break;
Martin Radev802abe02016-08-04 17:48:32 +0300422 case EvqComputeIn:
423 message = "can't modify work group size variable";
424 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400425 default:
426 //
427 // Type that can't be written to?
428 //
429 if (node->getBasicType() == EbtVoid)
430 {
431 message = "can't modify void";
432 }
433 if (IsSampler(node->getBasicType()))
434 {
435 message = "can't modify a sampler";
436 }
Martin Radev2cc85b32016-08-05 16:22:53 +0300437 if (IsImage(node->getBasicType()))
438 {
439 message = "can't modify an image";
440 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000441 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000442
Arun Patole7e7e68d2015-05-22 12:02:25 +0530443 if (message == 0 && binaryNode == 0 && symNode == 0)
444 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000445 error(line, "l-value required", op);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000446
Olli Etuaho8a176262016-08-16 14:23:01 +0300447 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000448 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000449
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000450 //
451 // Everything else is okay, no error.
452 //
453 if (message == 0)
Olli Etuaho8a176262016-08-16 14:23:01 +0300454 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000455
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000456 //
457 // If we get here, we have an error and a message.
458 //
Arun Patole7e7e68d2015-05-22 12:02:25 +0530459 if (symNode)
460 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000461 const char *symbol = symNode->getSymbol().c_str();
462 std::stringstream reasonStream;
463 reasonStream << "l-value required (" << message << " \"" << symbol << "\")";
464 std::string reason = reasonStream.str();
465 error(line, reason.c_str(), op);
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000466 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530467 else
468 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000469 std::stringstream reasonStream;
470 reasonStream << "l-value required (" << message << ")";
471 std::string reason = reasonStream.str();
472 error(line, reason.c_str(), op);
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000473 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000474
Olli Etuaho8a176262016-08-16 14:23:01 +0300475 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000476}
477
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000478// Both test, and if necessary spit out an error, to see if the node is really
479// a constant.
Olli Etuaho856c4972016-08-08 11:38:39 +0300480void TParseContext::checkIsConst(TIntermTyped *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000481{
Olli Etuaho383b7912016-08-05 11:22:59 +0300482 if (node->getQualifier() != EvqConst)
483 {
484 error(node->getLine(), "constant expression required", "");
485 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000486}
487
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000488// Both test, and if necessary spit out an error, to see if the node is really
489// an integer.
Olli Etuaho856c4972016-08-08 11:38:39 +0300490void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000491{
Olli Etuaho383b7912016-08-05 11:22:59 +0300492 if (!node->isScalarInt())
493 {
494 error(node->getLine(), "integer expression required", token);
495 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000496}
497
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000498// Both test, and if necessary spit out an error, to see if we are currently
499// globally scoped.
Qiankun Miaof69682b2016-08-16 14:50:42 +0800500bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000501{
Olli Etuaho856c4972016-08-08 11:38:39 +0300502 if (!symbolTable.atGlobalLevel())
Olli Etuaho383b7912016-08-05 11:22:59 +0300503 {
504 error(line, "only allowed at global scope", token);
Qiankun Miaof69682b2016-08-16 14:50:42 +0800505 return false;
Olli Etuaho383b7912016-08-05 11:22:59 +0300506 }
Qiankun Miaof69682b2016-08-16 14:50:42 +0800507 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508}
509
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000510// For now, keep it simple: if it starts "gl_", it's reserved, independent
511// of scope. Except, if the symbol table is at the built-in push-level,
512// which is when we are parsing built-ins.
alokp@chromium.org613ef312010-07-21 18:54:22 +0000513// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
514// webgl shader.
Olli Etuaho856c4972016-08-08 11:38:39 +0300515bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000516{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530517 static const char *reservedErrMsg = "reserved built-in name";
518 if (!symbolTable.atBuiltInLevel())
519 {
520 if (identifier.compare(0, 3, "gl_") == 0)
521 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000522 error(line, reservedErrMsg, "gl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300523 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000524 }
Jamie Madillacb4b812016-11-07 13:50:29 -0500525 if (sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530526 {
527 if (identifier.compare(0, 6, "webgl_") == 0)
528 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000529 error(line, reservedErrMsg, "webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300530 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000531 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530532 if (identifier.compare(0, 7, "_webgl_") == 0)
533 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000534 error(line, reservedErrMsg, "_webgl_");
Olli Etuaho8a176262016-08-16 14:23:01 +0300535 return false;
alokp@chromium.org613ef312010-07-21 18:54:22 +0000536 }
537 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530538 if (identifier.find("__") != TString::npos)
539 {
540 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400541 "identifiers containing two consecutive underscores (__) are reserved as "
542 "possible future keywords",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530543 identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300544 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000545 }
546 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000547
Olli Etuaho8a176262016-08-16 14:23:01 +0300548 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000549}
550
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000551// Make sure there is enough data provided to the constructor to build
552// something of the type of the constructor. Also returns the type of
553// the constructor.
Olli Etuaho856c4972016-08-08 11:38:39 +0300554bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800555 const TIntermSequence *arguments,
Olli Etuaho856c4972016-08-08 11:38:39 +0300556 TOperator op,
557 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000558{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000559 bool constructingMatrix = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400560 switch (op)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530561 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400562 case EOpConstructMat2:
563 case EOpConstructMat2x3:
564 case EOpConstructMat2x4:
565 case EOpConstructMat3x2:
566 case EOpConstructMat3:
567 case EOpConstructMat3x4:
568 case EOpConstructMat4x2:
569 case EOpConstructMat4x3:
570 case EOpConstructMat4:
571 constructingMatrix = true;
572 break;
573 default:
574 break;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000575 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000576
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000577 //
578 // Note: It's okay to have too many components available, but not okay to have unused
579 // arguments. 'full' will go to true when enough args have been seen. If we loop
580 // again, there is an extra argument, so 'overfull' will become true.
581 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000582
Jamie Madillb98c3a82015-07-23 14:26:04 -0400583 size_t size = 0;
Jamie Madillb98c3a82015-07-23 14:26:04 -0400584 bool full = false;
585 bool overFull = false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000586 bool matrixInMatrix = false;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500587 bool arrayArg = false;
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800588 for (TIntermNode *arg : *arguments)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530589 {
Olli Etuaho72d10202017-01-19 15:58:30 +0000590 const TIntermTyped *argTyped = arg->getAsTyped();
591 size += argTyped->getType().getObjectSize();
Arun Patole7e7e68d2015-05-22 12:02:25 +0530592
Olli Etuaho72d10202017-01-19 15:58:30 +0000593 if (constructingMatrix && argTyped->getType().isMatrix())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000594 matrixInMatrix = true;
595 if (full)
596 overFull = true;
Olli Etuaho856c4972016-08-08 11:38:39 +0300597 if (op != EOpConstructStruct && !type.isArray() && size >= type.getObjectSize())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000598 full = true;
Olli Etuaho72d10202017-01-19 15:58:30 +0000599 if (argTyped->getType().isArray())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000600 arrayArg = true;
601 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530602
Olli Etuaho856c4972016-08-08 11:38:39 +0300603 if (type.isArray())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300604 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300605 // The size of an unsized constructor should already have been determined.
606 ASSERT(!type.isUnsizedArray());
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800607 if (static_cast<size_t>(type.getArraySize()) != arguments->size())
Olli Etuaho376f1b52015-04-13 13:23:41 +0300608 {
609 error(line, "array constructor needs one argument per array element", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300610 return false;
Olli Etuaho376f1b52015-04-13 13:23:41 +0300611 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000612 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000613
Arun Patole7e7e68d2015-05-22 12:02:25 +0530614 if (arrayArg && op != EOpConstructStruct)
615 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000616 error(line, "constructing from a non-dereferenced array", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300617 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000618 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000619
Olli Etuaho856c4972016-08-08 11:38:39 +0300620 if (matrixInMatrix && !type.isArray())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530621 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800622 if (arguments->size() != 1)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530623 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400624 error(line, "constructing matrix from matrix can only take one argument",
625 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300626 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000627 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000628 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000629
Arun Patole7e7e68d2015-05-22 12:02:25 +0530630 if (overFull)
631 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000632 error(line, "too many arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300633 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000634 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530635
Olli Etuaho856c4972016-08-08 11:38:39 +0300636 if (op == EOpConstructStruct && !type.isArray() &&
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800637 type.getStruct()->fields().size() != arguments->size())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530638 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400639 error(line,
640 "Number of constructor parameters does not match the number of structure fields",
641 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300642 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000643 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000644
Olli Etuaho856c4972016-08-08 11:38:39 +0300645 if (!type.isMatrix() || !matrixInMatrix)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530646 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300647 if ((op != EOpConstructStruct && size != 1 && size < type.getObjectSize()) ||
648 (op == EOpConstructStruct && size < type.getObjectSize()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530649 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000650 error(line, "not enough data provided for construction", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300651 return false;
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000652 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000653 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000654
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800655 if (arguments->empty())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530656 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200657 error(line, "constructor does not have any arguments", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300658 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000659 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200660
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800661 for (TIntermNode *const &argNode : *arguments)
Arun Patole7e7e68d2015-05-22 12:02:25 +0530662 {
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200663 TIntermTyped *argTyped = argNode->getAsTyped();
664 ASSERT(argTyped != nullptr);
665 if (op != EOpConstructStruct && IsSampler(argTyped->getBasicType()))
666 {
667 error(line, "cannot convert a sampler", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300668 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200669 }
Martin Radev2cc85b32016-08-05 16:22:53 +0300670 if (op != EOpConstructStruct && IsImage(argTyped->getBasicType()))
671 {
672 error(line, "cannot convert an image", "constructor");
673 return false;
674 }
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200675 if (argTyped->getBasicType() == EbtVoid)
676 {
677 error(line, "cannot convert a void", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300678 return false;
Olli Etuaho15c2ac32015-11-09 15:51:43 +0200679 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000680 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000681
Olli Etuaho856c4972016-08-08 11:38:39 +0300682 if (type.isArray())
683 {
684 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
685 // the array.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800686 for (TIntermNode *const &argNode : *arguments)
Olli Etuaho856c4972016-08-08 11:38:39 +0300687 {
688 const TType &argType = argNode->getAsTyped()->getType();
Jamie Madill34bf2d92017-02-06 13:40:59 -0500689 // It has already been checked that the argument is not an array, but we can arrive
690 // here due to prior error conditions.
691 if (argType.isArray())
692 {
693 return false;
694 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300695 if (!argType.sameElementType(type))
696 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000697 error(line, "Array constructor argument has an incorrect type", "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300698 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300699 }
700 }
701 }
702 else if (op == EOpConstructStruct)
703 {
704 const TFieldList &fields = type.getStruct()->fields();
Olli Etuaho856c4972016-08-08 11:38:39 +0300705
706 for (size_t i = 0; i < fields.size(); i++)
707 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -0800708 if (i >= arguments->size() ||
709 (*arguments)[i]->getAsTyped()->getType() != *fields[i]->type())
Olli Etuaho856c4972016-08-08 11:38:39 +0300710 {
711 error(line, "Structure constructor arguments do not match structure fields",
Olli Etuaho4de340a2016-12-16 09:32:03 +0000712 "constructor");
Olli Etuaho8a176262016-08-16 14:23:01 +0300713 return false;
Olli Etuaho856c4972016-08-08 11:38:39 +0300714 }
715 }
716 }
717
Olli Etuaho8a176262016-08-16 14:23:01 +0300718 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000719}
720
Jamie Madillb98c3a82015-07-23 14:26:04 -0400721// This function checks to see if a void variable has been declared and raise an error message for
722// such a case
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000723//
724// returns true in case of an error
725//
Olli Etuaho856c4972016-08-08 11:38:39 +0300726bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400727 const TString &identifier,
728 const TBasicType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000729{
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300730 if (type == EbtVoid)
731 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000732 error(line, "illegal use of type 'void'", identifier.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +0300733 return false;
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +0300734 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000735
Olli Etuaho8a176262016-08-16 14:23:01 +0300736 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000737}
738
Jamie Madillb98c3a82015-07-23 14:26:04 -0400739// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300740// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300741void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000742{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530743 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
744 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000745 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530746 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000747}
748
Jamie Madillb98c3a82015-07-23 14:26:04 -0400749// This function checks to see if the node (for the expression) contains a scalar boolean expression
Olli Etuaho383b7912016-08-05 11:22:59 +0300750// or not.
Olli Etuaho856c4972016-08-08 11:38:39 +0300751void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000752{
Martin Radev4a9cd802016-09-01 16:51:51 +0300753 if (pType.getBasicType() != EbtBool || pType.isAggregate())
Arun Patole7e7e68d2015-05-22 12:02:25 +0530754 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000755 error(line, "boolean expression expected", "");
Arun Patole7e7e68d2015-05-22 12:02:25 +0530756 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000757}
758
Olli Etuaho856c4972016-08-08 11:38:39 +0300759bool TParseContext::checkIsNotSampler(const TSourceLoc &line,
Martin Radev4a9cd802016-09-01 16:51:51 +0300760 const TTypeSpecifierNonArray &pType,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400761 const char *reason)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000762{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530763 if (pType.type == EbtStruct)
764 {
Martin Radev2cc85b32016-08-05 16:22:53 +0300765 if (ContainsSampler(*pType.userDef))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530766 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000767 std::stringstream reasonStream;
768 reasonStream << reason << " (structure contains a sampler)";
769 std::string reasonStr = reasonStream.str();
770 error(line, reasonStr.c_str(), getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300771 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000772 }
Arun Patole7e7e68d2015-05-22 12:02:25 +0530773
Olli Etuaho8a176262016-08-16 14:23:01 +0300774 return true;
Arun Patole7e7e68d2015-05-22 12:02:25 +0530775 }
776 else if (IsSampler(pType.type))
777 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000778 error(line, reason, getBasicString(pType.type));
Olli Etuaho8a176262016-08-16 14:23:01 +0300779 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000780 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000781
Olli Etuaho8a176262016-08-16 14:23:01 +0300782 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000783}
784
Martin Radev2cc85b32016-08-05 16:22:53 +0300785bool TParseContext::checkIsNotImage(const TSourceLoc &line,
786 const TTypeSpecifierNonArray &pType,
787 const char *reason)
788{
789 if (pType.type == EbtStruct)
790 {
791 if (ContainsImage(*pType.userDef))
792 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000793 std::stringstream reasonStream;
794 reasonStream << reason << " (structure contains an image)";
795 std::string reasonStr = reasonStream.str();
796 error(line, reasonStr.c_str(), getBasicString(pType.type));
Martin Radev2cc85b32016-08-05 16:22:53 +0300797
798 return false;
799 }
800
801 return true;
802 }
803 else if (IsImage(pType.type))
804 {
805 error(line, reason, getBasicString(pType.type));
806
807 return false;
808 }
809
810 return true;
811}
812
Olli Etuaho856c4972016-08-08 11:38:39 +0300813void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
814 const TPublicType &pType)
Jamie Madill0bd18df2013-06-20 11:55:52 -0400815{
816 if (pType.layoutQualifier.location != -1)
817 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400818 error(line, "location must only be specified for a single input or output variable",
819 "location");
Jamie Madill0bd18df2013-06-20 11:55:52 -0400820 }
Jamie Madill0bd18df2013-06-20 11:55:52 -0400821}
822
Olli Etuaho856c4972016-08-08 11:38:39 +0300823void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
824 const TLayoutQualifier &layoutQualifier)
825{
826 if (layoutQualifier.location != -1)
827 {
Olli Etuaho4de340a2016-12-16 09:32:03 +0000828 error(location, "invalid layout qualifier: only valid on program inputs and outputs",
829 "location");
Olli Etuaho856c4972016-08-08 11:38:39 +0300830 }
831}
832
Martin Radev2cc85b32016-08-05 16:22:53 +0300833void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
834 TQualifier qualifier,
835 const TType &type)
836{
837 checkOutParameterIsNotSampler(line, qualifier, type);
838 checkOutParameterIsNotImage(line, qualifier, type);
839}
840
Olli Etuaho856c4972016-08-08 11:38:39 +0300841void TParseContext::checkOutParameterIsNotSampler(const TSourceLoc &line,
842 TQualifier qualifier,
843 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000844{
Martin Radev2cc85b32016-08-05 16:22:53 +0300845 ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
846 if (IsSampler(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530847 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000848 error(line, "samplers cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000849 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000850}
851
Martin Radev2cc85b32016-08-05 16:22:53 +0300852void TParseContext::checkOutParameterIsNotImage(const TSourceLoc &line,
853 TQualifier qualifier,
854 const TType &type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000855{
Martin Radev2cc85b32016-08-05 16:22:53 +0300856 ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
857 if (IsImage(type.getBasicType()))
Arun Patole7e7e68d2015-05-22 12:02:25 +0530858 {
Martin Radev2cc85b32016-08-05 16:22:53 +0300859 error(line, "images cannot be output parameters", type.getBasicString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000860 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000861}
862
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000863// Do size checking for an array type's size.
Olli Etuaho856c4972016-08-08 11:38:39 +0300864unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000865{
Arun Patole7e7e68d2015-05-22 12:02:25 +0530866 TIntermConstantUnion *constant = expr->getAsConstantUnion();
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000867
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200868 // TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
869 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
870 // fold as array size.
871 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000872 {
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +0000873 error(line, "array size must be a constant integer expression", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300874 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000875 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000876
Olli Etuaho856c4972016-08-08 11:38:39 +0300877 unsigned int size = 0u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400878
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000879 if (constant->getBasicType() == EbtUInt)
880 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300881 size = constant->getUConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000882 }
883 else
884 {
Olli Etuaho856c4972016-08-08 11:38:39 +0300885 int signedSize = constant->getIConst(0);
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000886
Olli Etuaho856c4972016-08-08 11:38:39 +0300887 if (signedSize < 0)
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000888 {
Nicolas Capens906744a2014-06-06 15:18:07 -0400889 error(line, "array size must be non-negative", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300890 return 1u;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000891 }
Nicolas Capens906744a2014-06-06 15:18:07 -0400892
Olli Etuaho856c4972016-08-08 11:38:39 +0300893 size = static_cast<unsigned int>(signedSize);
Nicolas Capens906744a2014-06-06 15:18:07 -0400894 }
895
Olli Etuaho856c4972016-08-08 11:38:39 +0300896 if (size == 0u)
Nicolas Capens906744a2014-06-06 15:18:07 -0400897 {
898 error(line, "array size must be greater than zero", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300899 return 1u;
Nicolas Capens906744a2014-06-06 15:18:07 -0400900 }
901
902 // The size of arrays is restricted here to prevent issues further down the
903 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
904 // 4096 registers so this should be reasonable even for aggressively optimizable code.
905 const unsigned int sizeLimit = 65536;
906
Olli Etuaho856c4972016-08-08 11:38:39 +0300907 if (size > sizeLimit)
Nicolas Capens906744a2014-06-06 15:18:07 -0400908 {
909 error(line, "array size too large", "");
Olli Etuaho856c4972016-08-08 11:38:39 +0300910 return 1u;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000911 }
Olli Etuaho856c4972016-08-08 11:38:39 +0300912
913 return size;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000914}
915
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000916// See if this qualifier can be an array.
Olli Etuaho8a176262016-08-16 14:23:01 +0300917bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
918 const TPublicType &elementQualifier)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000919{
Olli Etuaho8a176262016-08-16 14:23:01 +0300920 if ((elementQualifier.qualifier == EvqAttribute) ||
921 (elementQualifier.qualifier == EvqVertexIn) ||
922 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
Olli Etuaho3739d232015-04-08 12:23:44 +0300923 {
Jamie Madillb98c3a82015-07-23 14:26:04 -0400924 error(line, "cannot declare arrays of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300925 TType(elementQualifier).getQualifierString());
926 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000927 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000928
Olli Etuaho8a176262016-08-16 14:23:01 +0300929 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000930}
931
Olli Etuaho8a176262016-08-16 14:23:01 +0300932// See if this element type can be formed into an array.
933bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &elementType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000934{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000935 //
936 // Can the type be an array?
937 //
Olli Etuaho8a176262016-08-16 14:23:01 +0300938 if (elementType.array)
Jamie Madill06145232015-05-13 13:10:01 -0400939 {
Olli Etuaho8a176262016-08-16 14:23:01 +0300940 error(line, "cannot declare arrays of arrays",
941 TType(elementType).getCompleteString().c_str());
942 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000943 }
Olli Etuahocc36b982015-07-10 14:14:18 +0300944 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
945 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
946 // 4.3.4).
Martin Radev4a9cd802016-09-01 16:51:51 +0300947 if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
Olli Etuaho8a176262016-08-16 14:23:01 +0300948 sh::IsVarying(elementType.qualifier))
Olli Etuahocc36b982015-07-10 14:14:18 +0300949 {
950 error(line, "cannot declare arrays of structs of this qualifier",
Olli Etuaho8a176262016-08-16 14:23:01 +0300951 TType(elementType).getCompleteString().c_str());
952 return false;
Olli Etuahocc36b982015-07-10 14:14:18 +0300953 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000954
Olli Etuaho8a176262016-08-16 14:23:01 +0300955 return true;
956}
957
958// Check if this qualified element type can be formed into an array.
959bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
960 const TPublicType &elementType)
961{
962 if (checkIsValidTypeForArray(indexLocation, elementType))
963 {
964 return checkIsValidQualifierForArray(indexLocation, elementType);
965 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000966 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000967}
968
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000969// Enforce non-initializer type/qualifier rules.
Olli Etuaho856c4972016-08-08 11:38:39 +0300970void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
971 const TString &identifier,
972 TPublicType *type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000973{
Olli Etuaho3739d232015-04-08 12:23:44 +0300974 ASSERT(type != nullptr);
975 if (type->qualifier == EvqConst)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000976 {
977 // Make the qualifier make sense.
Olli Etuaho3739d232015-04-08 12:23:44 +0300978 type->qualifier = EvqTemporary;
979
980 // Generate informative error messages for ESSL1.
981 // In ESSL3 arrays and structures containing arrays can be constant.
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400982 if (mShaderVersion < 300 && type->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000983 {
Arun Patole7e7e68d2015-05-22 12:02:25 +0530984 error(line,
Jamie Madillb98c3a82015-07-23 14:26:04 -0400985 "structures containing arrays may not be declared constant since they cannot be "
986 "initialized",
Arun Patole7e7e68d2015-05-22 12:02:25 +0530987 identifier.c_str());
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000988 }
989 else
990 {
991 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
992 }
Olli Etuaho383b7912016-08-05 11:22:59 +0300993 return;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000994 }
Olli Etuaho376f1b52015-04-13 13:23:41 +0300995 if (type->isUnsizedArray())
996 {
997 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
Olli Etuaho376f1b52015-04-13 13:23:41 +0300998 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000999}
1000
Olli Etuaho2935c582015-04-08 14:32:06 +03001001// Do some simple checks that are shared between all variable declarations,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001002// and update the symbol table.
1003//
Olli Etuaho2935c582015-04-08 14:32:06 +03001004// Returns true if declaring the variable succeeded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001005//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001006bool TParseContext::declareVariable(const TSourceLoc &line,
1007 const TString &identifier,
1008 const TType &type,
Olli Etuaho2935c582015-04-08 14:32:06 +03001009 TVariable **variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001010{
Olli Etuaho2935c582015-04-08 14:32:06 +03001011 ASSERT((*variable) == nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001012
Olli Etuaho856c4972016-08-08 11:38:39 +03001013 bool needsReservedCheck = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001014
Olli Etuaho2935c582015-04-08 14:32:06 +03001015 // gl_LastFragData may be redeclared with a new precision qualifier
1016 if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
1017 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001018 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
1019 symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
Olli Etuaho856c4972016-08-08 11:38:39 +03001020 if (static_cast<int>(type.getArraySize()) == maxDrawBuffers->getConstPointer()->getIConst())
Olli Etuaho2935c582015-04-08 14:32:06 +03001021 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001022 if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
Olli Etuaho2935c582015-04-08 14:32:06 +03001023 {
Olli Etuaho8a176262016-08-16 14:23:01 +03001024 needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
Olli Etuaho2935c582015-04-08 14:32:06 +03001025 }
1026 }
1027 else
1028 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001029 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
1030 identifier.c_str());
Olli Etuaho2935c582015-04-08 14:32:06 +03001031 return false;
1032 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001033 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001034
Olli Etuaho8a176262016-08-16 14:23:01 +03001035 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
Olli Etuaho2935c582015-04-08 14:32:06 +03001036 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001037
Olli Etuaho2935c582015-04-08 14:32:06 +03001038 (*variable) = new TVariable(&identifier, type);
1039 if (!symbolTable.declare(*variable))
1040 {
1041 error(line, "redefinition", identifier.c_str());
Jamie Madill1a4b1b32015-07-23 18:27:13 -04001042 *variable = nullptr;
Olli Etuaho2935c582015-04-08 14:32:06 +03001043 return false;
1044 }
1045
Olli Etuaho8a176262016-08-16 14:23:01 +03001046 if (!checkIsNonVoid(line, identifier, type.getBasicType()))
Olli Etuaho2935c582015-04-08 14:32:06 +03001047 return false;
1048
1049 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001050}
1051
Martin Radev70866b82016-07-22 15:27:42 +03001052void TParseContext::checkIsParameterQualifierValid(
1053 const TSourceLoc &line,
1054 const TTypeQualifierBuilder &typeQualifierBuilder,
1055 TType *type)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301056{
Olli Etuaho77ba4082016-12-16 12:01:18 +00001057 TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03001058
1059 if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
Arun Patole7e7e68d2015-05-22 12:02:25 +05301060 {
Martin Radev2cc85b32016-08-05 16:22:53 +03001061 checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type);
1062 }
1063
1064 if (!IsImage(type->getBasicType()))
1065 {
1066 checkIsMemoryQualifierNotSpecified(typeQualifier.memoryQualifier, line);
1067 }
1068 else
1069 {
1070 type->setMemoryQualifier(typeQualifier.memoryQualifier);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001071 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001072
Martin Radev70866b82016-07-22 15:27:42 +03001073 type->setQualifier(typeQualifier.qualifier);
1074
1075 if (typeQualifier.precision != EbpUndefined)
1076 {
1077 type->setPrecision(typeQualifier.precision);
1078 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001079}
1080
Olli Etuaho856c4972016-08-08 11:38:39 +03001081bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001082{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001083 const TExtensionBehavior &extBehavior = extensionBehavior();
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001084 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
Arun Patole7e7e68d2015-05-22 12:02:25 +05301085 if (iter == extBehavior.end())
1086 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001087 error(line, "extension is not supported", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001088 return false;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001089 }
zmo@google.comf5450912011-09-09 01:37:19 +00001090 // In GLSL ES, an extension's default behavior is "disable".
Arun Patole7e7e68d2015-05-22 12:02:25 +05301091 if (iter->second == EBhDisable || iter->second == EBhUndefined)
1092 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00001093 // TODO(oetuaho@nvidia.com): This is slightly hacky. Might be better if symbols could be
1094 // associated with more than one extension.
1095 if (extension == "GL_OVR_multiview")
1096 {
1097 return checkCanUseExtension(line, "GL_OVR_multiview2");
1098 }
Olli Etuaho4de340a2016-12-16 09:32:03 +00001099 error(line, "extension is disabled", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001100 return false;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001101 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301102 if (iter->second == EBhWarn)
1103 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001104 warning(line, "extension is being used", extension.c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03001105 return true;
alokp@chromium.org8815d7f2010-09-09 17:30:03 +00001106 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001107
Olli Etuaho8a176262016-08-16 14:23:01 +03001108 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001109}
1110
Martin Radevb8b01222016-11-20 23:25:53 +02001111void TParseContext::emptyDeclarationErrorCheck(const TPublicType &publicType,
1112 const TSourceLoc &location)
1113{
1114 if (publicType.isUnsizedArray())
1115 {
1116 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1117 // error. It is assumed that this applies to empty declarations as well.
1118 error(location, "empty array declaration needs to specify a size", "");
1119 }
1120 if (publicType.qualifier == EvqShared && !publicType.layoutQualifier.isEmpty())
1121 {
1122 error(location, "Shared memory declarations cannot have layout specified", "layout");
1123 }
1124}
1125
Jamie Madillb98c3a82015-07-23 14:26:04 -04001126// These checks are common for all declarations starting a declarator list, and declarators that
1127// follow an empty declaration.
Olli Etuaho383b7912016-08-05 11:22:59 +03001128void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
Jamie Madillb98c3a82015-07-23 14:26:04 -04001129 const TSourceLoc &identifierLocation)
Jamie Madilla5efff92013-06-06 11:56:47 -04001130{
Olli Etuahofa33d582015-04-09 14:33:12 +03001131 switch (publicType.qualifier)
1132 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001133 case EvqVaryingIn:
1134 case EvqVaryingOut:
1135 case EvqAttribute:
1136 case EvqVertexIn:
1137 case EvqFragmentOut:
Martin Radev802abe02016-08-04 17:48:32 +03001138 case EvqComputeIn:
Martin Radev4a9cd802016-09-01 16:51:51 +03001139 if (publicType.getBasicType() == EbtStruct)
Jamie Madillb98c3a82015-07-23 14:26:04 -04001140 {
1141 error(identifierLocation, "cannot be used with a structure",
1142 getQualifierString(publicType.qualifier));
Olli Etuaho383b7912016-08-05 11:22:59 +03001143 return;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001144 }
Olli Etuahofa33d582015-04-09 14:33:12 +03001145
Jamie Madillb98c3a82015-07-23 14:26:04 -04001146 default:
1147 break;
Olli Etuahofa33d582015-04-09 14:33:12 +03001148 }
1149
Jamie Madillb98c3a82015-07-23 14:26:04 -04001150 if (publicType.qualifier != EvqUniform &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001151 !checkIsNotSampler(identifierLocation, publicType.typeSpecifierNonArray,
1152 "samplers must be uniform"))
Olli Etuahofa33d582015-04-09 14:33:12 +03001153 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001154 return;
Olli Etuahofa33d582015-04-09 14:33:12 +03001155 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001156 if (publicType.qualifier != EvqUniform &&
1157 !checkIsNotImage(identifierLocation, publicType.typeSpecifierNonArray,
1158 "images must be uniform"))
1159 {
1160 return;
1161 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001162
1163 // check for layout qualifier issues
1164 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
1165
1166 if (layoutQualifier.matrixPacking != EmpUnspecified)
1167 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001168 error(identifierLocation, "layout qualifier only valid for interface blocks",
1169 getMatrixPackingString(layoutQualifier.matrixPacking));
Olli Etuaho383b7912016-08-05 11:22:59 +03001170 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001171 }
1172
1173 if (layoutQualifier.blockStorage != EbsUnspecified)
1174 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001175 error(identifierLocation, "layout qualifier only valid for interface blocks",
1176 getBlockStorageString(layoutQualifier.blockStorage));
Olli Etuaho383b7912016-08-05 11:22:59 +03001177 return;
Jamie Madilla5efff92013-06-06 11:56:47 -04001178 }
1179
Olli Etuaho383b7912016-08-05 11:22:59 +03001180 if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut)
Jamie Madilla5efff92013-06-06 11:56:47 -04001181 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001182 checkLocationIsNotSpecified(identifierLocation, publicType.layoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04001183 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001184
1185 if (IsImage(publicType.getBasicType()))
1186 {
1187
1188 switch (layoutQualifier.imageInternalFormat)
1189 {
1190 case EiifRGBA32F:
1191 case EiifRGBA16F:
1192 case EiifR32F:
1193 case EiifRGBA8:
1194 case EiifRGBA8_SNORM:
1195 if (!IsFloatImage(publicType.getBasicType()))
1196 {
1197 error(identifierLocation,
1198 "internal image format requires a floating image type",
1199 getBasicString(publicType.getBasicType()));
1200 return;
1201 }
1202 break;
1203 case EiifRGBA32I:
1204 case EiifRGBA16I:
1205 case EiifRGBA8I:
1206 case EiifR32I:
1207 if (!IsIntegerImage(publicType.getBasicType()))
1208 {
1209 error(identifierLocation,
1210 "internal image format requires an integer image type",
1211 getBasicString(publicType.getBasicType()));
1212 return;
1213 }
1214 break;
1215 case EiifRGBA32UI:
1216 case EiifRGBA16UI:
1217 case EiifRGBA8UI:
1218 case EiifR32UI:
1219 if (!IsUnsignedImage(publicType.getBasicType()))
1220 {
1221 error(identifierLocation,
1222 "internal image format requires an unsigned image type",
1223 getBasicString(publicType.getBasicType()));
1224 return;
1225 }
1226 break;
1227 case EiifUnspecified:
1228 error(identifierLocation, "layout qualifier", "No image internal format specified");
1229 return;
1230 default:
1231 error(identifierLocation, "layout qualifier", "unrecognized token");
1232 return;
1233 }
1234
1235 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
1236 switch (layoutQualifier.imageInternalFormat)
1237 {
1238 case EiifR32F:
1239 case EiifR32I:
1240 case EiifR32UI:
1241 break;
1242 default:
1243 if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
1244 {
1245 error(identifierLocation, "layout qualifier",
1246 "Except for images with the r32f, r32i and r32ui format qualifiers, "
1247 "image variables must be qualified readonly and/or writeonly");
1248 return;
1249 }
1250 break;
1251 }
1252 }
1253 else
1254 {
1255
1256 if (!checkInternalFormatIsNotSpecified(identifierLocation,
1257 layoutQualifier.imageInternalFormat))
1258 {
1259 return;
1260 }
1261
1262 if (!checkIsMemoryQualifierNotSpecified(publicType.memoryQualifier, identifierLocation))
1263 {
1264 return;
1265 }
1266 }
Jamie Madilla5efff92013-06-06 11:56:47 -04001267}
1268
Olli Etuaho856c4972016-08-08 11:38:39 +03001269void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1270 const TString &layoutQualifierName,
1271 int versionRequired)
Martin Radev802abe02016-08-04 17:48:32 +03001272{
1273
1274 if (mShaderVersion < versionRequired)
1275 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001276 error(location, "invalid layout qualifier: not supported", layoutQualifierName.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03001277 }
1278}
1279
Olli Etuaho856c4972016-08-08 11:38:39 +03001280bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1281 const TLayoutQualifier &layoutQualifier)
Martin Radev802abe02016-08-04 17:48:32 +03001282{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001283 const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
Martin Radev802abe02016-08-04 17:48:32 +03001284 for (size_t i = 0u; i < localSize.size(); ++i)
1285 {
1286 if (localSize[i] != -1)
1287 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001288 error(location,
1289 "invalid layout qualifier: only valid when used with 'in' in a compute shader "
1290 "global layout declaration",
1291 getWorkGroupSizeString(i));
Olli Etuaho8a176262016-08-16 14:23:01 +03001292 return false;
Martin Radev802abe02016-08-04 17:48:32 +03001293 }
1294 }
1295
Olli Etuaho8a176262016-08-16 14:23:01 +03001296 return true;
Martin Radev802abe02016-08-04 17:48:32 +03001297}
1298
Martin Radev2cc85b32016-08-05 16:22:53 +03001299bool TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
1300 TLayoutImageInternalFormat internalFormat)
1301{
1302 if (internalFormat != EiifUnspecified)
1303 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001304 error(location, "invalid layout qualifier: only valid when used with images",
1305 getImageInternalFormatString(internalFormat));
Martin Radev2cc85b32016-08-05 16:22:53 +03001306 return false;
1307 }
1308 return true;
1309}
1310
Olli Etuaho383b7912016-08-05 11:22:59 +03001311void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
Olli Etuaho856c4972016-08-08 11:38:39 +03001312 TIntermAggregate *fnCall)
Olli Etuahob6e07a62015-02-16 12:22:10 +02001313{
1314 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1315 {
1316 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1317 if (qual == EvqOut || qual == EvqInOut)
1318 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001319 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
Olli Etuaho8a176262016-08-16 14:23:01 +03001320 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
Olli Etuahob6e07a62015-02-16 12:22:10 +02001321 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001322 TString unmangledName =
1323 TFunction::unmangleName(fnCall->getFunctionSymbolInfo()->getName());
Olli Etuaho856c4972016-08-08 11:38:39 +03001324 error(argument->getLine(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00001325 "Constant value cannot be passed for 'out' or 'inout' parameters.",
1326 unmangledName.c_str());
Olli Etuaho383b7912016-08-05 11:22:59 +03001327 return;
Olli Etuahob6e07a62015-02-16 12:22:10 +02001328 }
1329 }
1330 }
Olli Etuahob6e07a62015-02-16 12:22:10 +02001331}
1332
Martin Radev70866b82016-07-22 15:27:42 +03001333void TParseContext::checkInvariantVariableQualifier(bool invariant,
1334 const TQualifier qualifier,
1335 const TSourceLoc &invariantLocation)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001336{
Martin Radev70866b82016-07-22 15:27:42 +03001337 if (!invariant)
1338 return;
1339
1340 if (mShaderVersion < 300)
Olli Etuaho37ad4742015-04-27 13:18:50 +03001341 {
Martin Radev70866b82016-07-22 15:27:42 +03001342 // input variables in the fragment shader can be also qualified as invariant
1343 if (!sh::CanBeInvariantESSL1(qualifier))
1344 {
1345 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1346 }
1347 }
1348 else
1349 {
1350 if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
1351 {
1352 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
1353 }
Olli Etuaho37ad4742015-04-27 13:18:50 +03001354 }
1355}
1356
Arun Patole7e7e68d2015-05-22 12:02:25 +05301357bool TParseContext::supportsExtension(const char *extension)
zmo@google.com09c323a2011-08-12 18:22:25 +00001358{
Jamie Madillb98c3a82015-07-23 14:26:04 -04001359 const TExtensionBehavior &extbehavior = extensionBehavior();
alokp@chromium.org73bc2982012-06-19 18:48:05 +00001360 TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1361 return (iter != extbehavior.end());
alokp@chromium.org8b851c62012-06-15 16:25:11 +00001362}
1363
Arun Patole7e7e68d2015-05-22 12:02:25 +05301364bool TParseContext::isExtensionEnabled(const char *extension) const
Jamie Madill5d287f52013-07-12 15:38:19 -04001365{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001366 return ::IsExtensionEnabled(extensionBehavior(), extension);
Jamie Madill5d287f52013-07-12 15:38:19 -04001367}
1368
Jamie Madillb98c3a82015-07-23 14:26:04 -04001369void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
1370 const char *extName,
1371 const char *behavior)
Jamie Madill075edd82013-07-08 13:30:19 -04001372{
1373 pp::SourceLocation srcLoc;
1374 srcLoc.file = loc.first_file;
1375 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001376 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
Jamie Madill075edd82013-07-08 13:30:19 -04001377}
1378
Jamie Madillb98c3a82015-07-23 14:26:04 -04001379void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
1380 const char *name,
1381 const char *value,
1382 bool stdgl)
Jamie Madill075edd82013-07-08 13:30:19 -04001383{
1384 pp::SourceLocation srcLoc;
1385 srcLoc.file = loc.first_file;
1386 srcLoc.line = loc.first_line;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001387 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
Jamie Madill075edd82013-07-08 13:30:19 -04001388}
1389
Martin Radev4c4c8e72016-08-04 12:25:34 +03001390sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
Martin Radev802abe02016-08-04 17:48:32 +03001391{
Martin Radev4c4c8e72016-08-04 12:25:34 +03001392 sh::WorkGroupSize result;
Martin Radev802abe02016-08-04 17:48:32 +03001393 for (size_t i = 0u; i < result.size(); ++i)
1394 {
1395 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
1396 {
1397 result[i] = 1;
1398 }
1399 else
1400 {
1401 result[i] = mComputeShaderLocalSize[i];
1402 }
1403 }
1404 return result;
1405}
1406
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001407/////////////////////////////////////////////////////////////////////////////////
1408//
1409// Non-Errors.
1410//
1411/////////////////////////////////////////////////////////////////////////////////
1412
Jamie Madill5c097022014-08-20 16:38:32 -04001413const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1414 const TString *name,
1415 const TSymbol *symbol)
1416{
1417 const TVariable *variable = NULL;
1418
1419 if (!symbol)
1420 {
1421 error(location, "undeclared identifier", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001422 }
1423 else if (!symbol->isVariable())
1424 {
1425 error(location, "variable expected", name->c_str());
Jamie Madill5c097022014-08-20 16:38:32 -04001426 }
1427 else
1428 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001429 variable = static_cast<const TVariable *>(symbol);
Jamie Madill5c097022014-08-20 16:38:32 -04001430
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001431 if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
Olli Etuaho383b7912016-08-05 11:22:59 +03001432 !variable->getExtension().empty())
Jamie Madill5c097022014-08-20 16:38:32 -04001433 {
Olli Etuaho856c4972016-08-08 11:38:39 +03001434 checkCanUseExtension(location, variable->getExtension());
Jamie Madill5c097022014-08-20 16:38:32 -04001435 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001436
1437 // Reject shaders using both gl_FragData and gl_FragColor
1438 TQualifier qualifier = variable->getType().getQualifier();
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001439 if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001440 {
1441 mUsesFragData = true;
1442 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001443 else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
Jamie Madill14e95b32015-05-07 10:10:41 -04001444 {
1445 mUsesFragColor = true;
1446 }
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001447 if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
1448 {
1449 mUsesSecondaryOutputs = true;
1450 }
Jamie Madill14e95b32015-05-07 10:10:41 -04001451
1452 // This validation is not quite correct - it's only an error to write to
1453 // both FragData and FragColor. For simplicity, and because users shouldn't
1454 // be rewarded for reading from undefined varaibles, return an error
1455 // if they are both referenced, rather than assigned.
1456 if (mUsesFragData && mUsesFragColor)
1457 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +03001458 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
1459 if (mUsesSecondaryOutputs)
1460 {
1461 errorMessage =
1462 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
1463 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
1464 }
1465 error(location, errorMessage, name->c_str());
Jamie Madill14e95b32015-05-07 10:10:41 -04001466 }
Martin Radevb0883602016-08-04 17:48:58 +03001467
1468 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
1469 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
1470 qualifier == EvqWorkGroupSize)
1471 {
1472 error(location,
1473 "It is an error to use gl_WorkGroupSize before declaring the local group size",
1474 "gl_WorkGroupSize");
1475 }
Jamie Madill5c097022014-08-20 16:38:32 -04001476 }
1477
1478 if (!variable)
1479 {
1480 TType type(EbtFloat, EbpUndefined);
1481 TVariable *fakeVariable = new TVariable(name, type);
1482 symbolTable.declare(fakeVariable);
1483 variable = fakeVariable;
1484 }
1485
1486 return variable;
1487}
1488
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001489TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
1490 const TString *name,
1491 const TSymbol *symbol)
1492{
1493 const TVariable *variable = getNamedVariable(location, name, symbol);
1494
Olli Etuaho09b04a22016-12-15 13:30:26 +00001495 if (variable->getType().getQualifier() == EvqViewIDOVR && IsWebGLBasedSpec(mShaderSpec) &&
1496 mShaderType == GL_FRAGMENT_SHADER && !isExtensionEnabled("GL_OVR_multiview2"))
1497 {
1498 // WEBGL_multiview spec
1499 error(location, "Need to enable OVR_multiview2 to use gl_ViewID_OVR in fragment shader",
1500 "gl_ViewID_OVR");
1501 }
1502
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001503 if (variable->getConstPointer())
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001504 {
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001505 const TConstantUnion *constArray = variable->getConstPointer();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001506 return intermediate.addConstantUnion(constArray, variable->getType(), location);
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001507 }
Olli Etuahoaecfa8e2016-12-09 12:47:26 +00001508 else if (variable->getType().getQualifier() == EvqWorkGroupSize &&
1509 mComputeShaderLocalSizeDeclared)
1510 {
1511 // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
1512 // needs to be added to the AST as a constant and not as a symbol.
1513 sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
1514 TConstantUnion *constArray = new TConstantUnion[3];
1515 for (size_t i = 0; i < 3; ++i)
1516 {
1517 constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
1518 }
1519
1520 ASSERT(variable->getType().getBasicType() == EbtUInt);
1521 ASSERT(variable->getType().getObjectSize() == 3);
1522
1523 TType type(variable->getType());
1524 type.setQualifier(EvqConst);
1525 return intermediate.addConstantUnion(constArray, type, location);
1526 }
Olli Etuaho82c29ed2015-11-03 13:06:54 +02001527 else
1528 {
1529 return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
1530 variable->getType(), location);
1531 }
1532}
1533
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001534//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001535// Initializers show up in several places in the grammar. Have one set of
1536// code to handle them here.
1537//
Jamie Madill3b5c2da2014-08-19 15:23:32 -04001538// Returns true on error, false if no error
1539//
Jamie Madillb98c3a82015-07-23 14:26:04 -04001540bool TParseContext::executeInitializer(const TSourceLoc &line,
1541 const TString &identifier,
1542 const TPublicType &pType,
1543 TIntermTyped *initializer,
Olli Etuaho13389b62016-10-16 11:48:18 +01001544 TIntermBinary **initNode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001545{
Olli Etuaho13389b62016-10-16 11:48:18 +01001546 ASSERT(initNode != nullptr);
1547 ASSERT(*initNode == nullptr);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001548 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001549
Olli Etuaho2935c582015-04-08 14:32:06 +03001550 TVariable *variable = nullptr;
Olli Etuaho376f1b52015-04-13 13:23:41 +03001551 if (type.isUnsizedArray())
1552 {
Olli Etuaho02bd82c2016-11-03 10:29:43 +00001553 // We have not checked yet whether the initializer actually is an array or not.
1554 if (initializer->isArray())
1555 {
1556 type.setArraySize(initializer->getArraySize());
1557 }
1558 else
1559 {
1560 // Having a non-array initializer for an unsized array will result in an error later,
1561 // so we don't generate an error message here.
1562 type.setArraySize(1u);
1563 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03001564 }
Olli Etuaho2935c582015-04-08 14:32:06 +03001565 if (!declareVariable(line, identifier, type, &variable))
1566 {
1567 return true;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001568 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001569
Olli Etuahob0c645e2015-05-12 14:25:36 +03001570 bool globalInitWarning = false;
Jamie Madillb98c3a82015-07-23 14:26:04 -04001571 if (symbolTable.atGlobalLevel() &&
1572 !ValidateGlobalInitializer(initializer, this, &globalInitWarning))
Olli Etuahob0c645e2015-05-12 14:25:36 +03001573 {
1574 // Error message does not completely match behavior with ESSL 1.00, but
1575 // we want to steer developers towards only using constant expressions.
1576 error(line, "global variable initializers must be constant expressions", "=");
1577 return true;
1578 }
1579 if (globalInitWarning)
1580 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001581 warning(
1582 line,
1583 "global variable initializers should be constant expressions "
1584 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
1585 "=");
Olli Etuahob0c645e2015-05-12 14:25:36 +03001586 }
1587
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001588 //
1589 // identifier must be of type constant, a global, or a temporary
1590 //
1591 TQualifier qualifier = variable->getType().getQualifier();
Arun Patole7e7e68d2015-05-22 12:02:25 +05301592 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
1593 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001594 error(line, " cannot initialize this type of qualifier ",
1595 variable->getType().getQualifierString());
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001596 return true;
1597 }
1598 //
1599 // test for and propagate constant
1600 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001601
Arun Patole7e7e68d2015-05-22 12:02:25 +05301602 if (qualifier == EvqConst)
1603 {
1604 if (qualifier != initializer->getType().getQualifier())
1605 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00001606 std::stringstream reasonStream;
1607 reasonStream << "assigning non-constant to '" << variable->getType().getCompleteString()
1608 << "'";
1609 std::string reason = reasonStream.str();
1610 error(line, reason.c_str(), "=");
alokp@chromium.org58e54292010-08-24 21:40:03 +00001611 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001612 return true;
1613 }
Arun Patole7e7e68d2015-05-22 12:02:25 +05301614 if (type != initializer->getType())
1615 {
1616 error(line, " non-matching types for const initializer ",
Jamie Madillb98c3a82015-07-23 14:26:04 -04001617 variable->getType().getQualifierString());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001618 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001619 return true;
1620 }
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001621
1622 // Save the constant folded value to the variable if possible. For example array
1623 // initializers are not folded, since that way copying the array literal to multiple places
1624 // in the shader is avoided.
1625 // TODO(oetuaho@nvidia.com): Consider constant folding array initialization in cases where
1626 // it would be beneficial.
Arun Patole7e7e68d2015-05-22 12:02:25 +05301627 if (initializer->getAsConstantUnion())
1628 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001629 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
Olli Etuaho13389b62016-10-16 11:48:18 +01001630 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001631 return false;
Arun Patole7e7e68d2015-05-22 12:02:25 +05301632 }
1633 else if (initializer->getAsSymbolNode())
1634 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04001635 const TSymbol *symbol =
1636 symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
1637 const TVariable *tVar = static_cast<const TVariable *>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001638
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001639 const TConstantUnion *constArray = tVar->getConstPointer();
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001640 if (constArray)
1641 {
1642 variable->shareConstPointer(constArray);
Olli Etuaho13389b62016-10-16 11:48:18 +01001643 *initNode = nullptr;
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001644 return false;
1645 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001646 }
1647 }
Olli Etuahoe7847b02015-03-16 11:56:12 +02001648
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001649 TIntermSymbol *intermSymbol = intermediate.addSymbol(
1650 variable->getUniqueId(), variable->getName(), variable->getType(), line);
Olli Etuaho13389b62016-10-16 11:48:18 +01001651 *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
1652 if (*initNode == nullptr)
Olli Etuahoe7847b02015-03-16 11:56:12 +02001653 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001654 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1655 return true;
Olli Etuahoe7847b02015-03-16 11:56:12 +02001656 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001657
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001658 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001659}
1660
Olli Etuaho0e3aee32016-10-27 12:56:38 +01001661void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
1662{
1663 checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
1664 typeSpecifier->getBasicType());
1665
1666 if (mShaderVersion < 300 && typeSpecifier->array)
1667 {
1668 error(typeSpecifier->getLine(), "not supported", "first-class array");
1669 typeSpecifier->clearArrayness();
1670 }
1671}
1672
Martin Radev70866b82016-07-22 15:27:42 +03001673TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
Arun Patole7e7e68d2015-05-22 12:02:25 +05301674 const TPublicType &typeSpecifier)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001675{
Olli Etuaho77ba4082016-12-16 12:01:18 +00001676 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001677
Martin Radev70866b82016-07-22 15:27:42 +03001678 TPublicType returnType = typeSpecifier;
1679 returnType.qualifier = typeQualifier.qualifier;
1680 returnType.invariant = typeQualifier.invariant;
1681 returnType.layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03001682 returnType.memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03001683 returnType.precision = typeSpecifier.precision;
1684
1685 if (typeQualifier.precision != EbpUndefined)
1686 {
1687 returnType.precision = typeQualifier.precision;
1688 }
1689
Martin Radev4a9cd802016-09-01 16:51:51 +03001690 checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
1691 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03001692
Martin Radev4a9cd802016-09-01 16:51:51 +03001693 checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
1694 typeSpecifier.getLine());
Martin Radev70866b82016-07-22 15:27:42 +03001695
Martin Radev4a9cd802016-09-01 16:51:51 +03001696 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03001697
Jamie Madill6e06b1f2015-05-14 10:01:17 -04001698 if (mShaderVersion < 300)
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001699 {
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001700 if (typeSpecifier.array)
1701 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001702 error(typeSpecifier.getLine(), "not supported", "first-class array");
Olli Etuahoc1ac41b2015-07-10 13:53:46 +03001703 returnType.clearArrayness();
1704 }
1705
Martin Radev70866b82016-07-22 15:27:42 +03001706 if (returnType.qualifier == EvqAttribute &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001707 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001708 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001709 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001710 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001711 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001712
Martin Radev70866b82016-07-22 15:27:42 +03001713 if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
Martin Radev4a9cd802016-09-01 16:51:51 +03001714 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001715 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001716 error(typeSpecifier.getLine(), "cannot be bool or int",
Martin Radev70866b82016-07-22 15:27:42 +03001717 getQualifierString(returnType.qualifier));
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001718 }
1719 }
1720 else
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001721 {
Martin Radev70866b82016-07-22 15:27:42 +03001722 if (!returnType.layoutQualifier.isEmpty())
Olli Etuahoabb0c382015-07-13 12:01:12 +03001723 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001724 checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
Olli Etuahoabb0c382015-07-13 12:01:12 +03001725 }
Martin Radev70866b82016-07-22 15:27:42 +03001726 if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
1727 returnType.qualifier == EvqFragmentOut)
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001728 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001729 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
1730 typeSpecifier.getLine());
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001731 }
Martin Radev70866b82016-07-22 15:27:42 +03001732 if (returnType.qualifier == EvqComputeIn)
Martin Radev802abe02016-08-04 17:48:32 +03001733 {
Martin Radev4a9cd802016-09-01 16:51:51 +03001734 error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
Martin Radev802abe02016-08-04 17:48:32 +03001735 "in");
Martin Radev802abe02016-08-04 17:48:32 +03001736 }
shannonwoods@chromium.org0f376ca2013-05-30 00:19:23 +00001737 }
1738
1739 return returnType;
1740}
1741
Olli Etuaho856c4972016-08-08 11:38:39 +03001742void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
1743 const TPublicType &type,
1744 const TSourceLoc &qualifierLocation)
Olli Etuahocc36b982015-07-10 14:14:18 +03001745{
1746 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
Martin Radev4a9cd802016-09-01 16:51:51 +03001747 if (type.getBasicType() == EbtBool)
Olli Etuahocc36b982015-07-10 14:14:18 +03001748 {
1749 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001750 }
1751
1752 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
1753 switch (qualifier)
1754 {
1755 case EvqVertexIn:
1756 // ESSL 3.00 section 4.3.4
1757 if (type.array)
1758 {
1759 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001760 }
1761 // Vertex inputs with a struct type are disallowed in singleDeclarationErrorCheck
1762 return;
1763 case EvqFragmentOut:
1764 // ESSL 3.00 section 4.3.6
Martin Radev4a9cd802016-09-01 16:51:51 +03001765 if (type.typeSpecifierNonArray.isMatrix())
Olli Etuahocc36b982015-07-10 14:14:18 +03001766 {
1767 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001768 }
1769 // Fragment outputs with a struct type are disallowed in singleDeclarationErrorCheck
1770 return;
1771 default:
1772 break;
1773 }
1774
1775 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
1776 // restrictions.
1777 bool typeContainsIntegers =
Martin Radev4a9cd802016-09-01 16:51:51 +03001778 (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
1779 type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
Olli Etuahocc36b982015-07-10 14:14:18 +03001780 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
1781 {
1782 error(qualifierLocation, "must use 'flat' interpolation here",
1783 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001784 }
1785
Martin Radev4a9cd802016-09-01 16:51:51 +03001786 if (type.getBasicType() == EbtStruct)
Olli Etuahocc36b982015-07-10 14:14:18 +03001787 {
1788 // ESSL 3.00 sections 4.3.4 and 4.3.6.
1789 // These restrictions are only implied by the ESSL 3.00 spec, but
1790 // the ESSL 3.10 spec lists these restrictions explicitly.
1791 if (type.array)
1792 {
1793 error(qualifierLocation, "cannot be an array of structures",
1794 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001795 }
1796 if (type.isStructureContainingArrays())
1797 {
1798 error(qualifierLocation, "cannot be a structure containing an array",
1799 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001800 }
1801 if (type.isStructureContainingType(EbtStruct))
1802 {
1803 error(qualifierLocation, "cannot be a structure containing a structure",
1804 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001805 }
1806 if (type.isStructureContainingType(EbtBool))
1807 {
1808 error(qualifierLocation, "cannot be a structure containing a bool",
1809 getQualifierString(qualifier));
Olli Etuahocc36b982015-07-10 14:14:18 +03001810 }
1811 }
1812}
1813
Martin Radev2cc85b32016-08-05 16:22:53 +03001814void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
1815{
1816 if (qualifier.getType() == QtStorage)
1817 {
1818 const TStorageQualifierWrapper &storageQualifier =
1819 static_cast<const TStorageQualifierWrapper &>(qualifier);
1820 if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
1821 !symbolTable.atGlobalLevel())
1822 {
1823 error(storageQualifier.getLine(),
1824 "Local variables can only use the const storage qualifier.",
1825 storageQualifier.getQualifierString().c_str());
1826 }
1827 }
1828}
1829
1830bool TParseContext::checkIsMemoryQualifierNotSpecified(const TMemoryQualifier &memoryQualifier,
1831 const TSourceLoc &location)
1832{
1833 if (memoryQualifier.readonly)
1834 {
1835 error(location, "Only allowed with images.", "readonly");
1836 return false;
1837 }
1838 if (memoryQualifier.writeonly)
1839 {
1840 error(location, "Only allowed with images.", "writeonly");
1841 return false;
1842 }
Martin Radev049edfa2016-11-11 14:35:37 +02001843 if (memoryQualifier.coherent)
1844 {
1845 error(location, "Only allowed with images.", "coherent");
1846 return false;
1847 }
1848 if (memoryQualifier.restrictQualifier)
1849 {
1850 error(location, "Only allowed with images.", "restrict");
1851 return false;
1852 }
1853 if (memoryQualifier.volatileQualifier)
1854 {
1855 error(location, "Only allowed with images.", "volatile");
1856 return false;
1857 }
Martin Radev2cc85b32016-08-05 16:22:53 +03001858 return true;
1859}
1860
Olli Etuaho13389b62016-10-16 11:48:18 +01001861TIntermDeclaration *TParseContext::parseSingleDeclaration(
1862 TPublicType &publicType,
1863 const TSourceLoc &identifierOrTypeLocation,
1864 const TString &identifier)
Jamie Madill60ed9812013-06-06 11:56:46 -04001865{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001866 TType type(publicType);
1867 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
1868 mDirectiveHandler.pragma().stdgl.invariantAll)
1869 {
1870 TQualifier qualifier = type.getQualifier();
1871
1872 // The directive handler has already taken care of rejecting invalid uses of this pragma
1873 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
1874 // affected variable declarations:
1875 //
1876 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
1877 // elsewhere, in TranslatorGLSL.)
1878 //
1879 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
1880 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
1881 // the way this is currently implemented we have to enable this compiler option before
1882 // parsing the shader and determining the shading language version it uses. If this were
1883 // implemented as a post-pass, the workaround could be more targeted.
1884 //
1885 // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
1886 // the specification, but there are desktop OpenGL drivers that expect that this is the
1887 // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
1888 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
1889 {
1890 type.setInvariant(true);
1891 }
1892 }
1893
1894 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, type, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001895
Olli Etuahobab4c082015-04-24 16:38:49 +03001896 bool emptyDeclaration = (identifier == "");
Olli Etuahofa33d582015-04-09 14:33:12 +03001897
Olli Etuahobab4c082015-04-24 16:38:49 +03001898 mDeferredSingleDeclarationErrorCheck = emptyDeclaration;
1899
Olli Etuaho13389b62016-10-16 11:48:18 +01001900 TIntermDeclaration *declaration = new TIntermDeclaration();
1901 declaration->setLine(identifierOrTypeLocation);
1902
Olli Etuahobab4c082015-04-24 16:38:49 +03001903 if (emptyDeclaration)
1904 {
Martin Radevb8b01222016-11-20 23:25:53 +02001905 emptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Olli Etuahobab4c082015-04-24 16:38:49 +03001906 }
1907 else
Jamie Madill60ed9812013-06-06 11:56:46 -04001908 {
Olli Etuaho383b7912016-08-05 11:22:59 +03001909 singleDeclarationErrorCheck(publicType, identifierOrTypeLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001910
Olli Etuaho856c4972016-08-08 11:38:39 +03001911 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001912
Olli Etuaho2935c582015-04-08 14:32:06 +03001913 TVariable *variable = nullptr;
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001914 declareVariable(identifierOrTypeLocation, identifier, type, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001915
1916 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01001917 {
Jamie Madill60ed9812013-06-06 11:56:46 -04001918 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01001919 }
Jamie Madill60ed9812013-06-06 11:56:46 -04001920 }
1921
Olli Etuaho13389b62016-10-16 11:48:18 +01001922 // We append the symbol even if the declaration is empty, mainly because of struct declarations
1923 // that may just declare a type.
1924 declaration->appendDeclarator(symbol);
1925
1926 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04001927}
1928
Olli Etuaho13389b62016-10-16 11:48:18 +01001929TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1930 const TSourceLoc &identifierLocation,
1931 const TString &identifier,
1932 const TSourceLoc &indexLocation,
1933 TIntermTyped *indexExpression)
Jamie Madill60ed9812013-06-06 11:56:46 -04001934{
Olli Etuahofa33d582015-04-09 14:33:12 +03001935 mDeferredSingleDeclarationErrorCheck = false;
1936
Olli Etuaho383b7912016-08-05 11:22:59 +03001937 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001938
Olli Etuaho856c4972016-08-08 11:38:39 +03001939 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001940
Olli Etuaho8a176262016-08-16 14:23:01 +03001941 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001942
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03001943 TType arrayType(publicType);
Jamie Madill60ed9812013-06-06 11:56:46 -04001944
Olli Etuaho856c4972016-08-08 11:38:39 +03001945 unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuahoe7847b02015-03-16 11:56:12 +02001946 // Make the type an array even if size check failed.
1947 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1948 arrayType.setArraySize(size);
Jamie Madill60ed9812013-06-06 11:56:46 -04001949
Olli Etuaho2935c582015-04-08 14:32:06 +03001950 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03001951 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill60ed9812013-06-06 11:56:46 -04001952
Olli Etuaho13389b62016-10-16 11:48:18 +01001953 TIntermDeclaration *declaration = new TIntermDeclaration();
1954 declaration->setLine(identifierLocation);
1955
Olli Etuahoe7847b02015-03-16 11:56:12 +02001956 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001957 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01001958 {
Jamie Madill60ed9812013-06-06 11:56:46 -04001959 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01001960 declaration->appendDeclarator(symbol);
1961 }
Jamie Madill60ed9812013-06-06 11:56:46 -04001962
Olli Etuaho13389b62016-10-16 11:48:18 +01001963 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04001964}
1965
Olli Etuaho13389b62016-10-16 11:48:18 +01001966TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
1967 const TSourceLoc &identifierLocation,
1968 const TString &identifier,
1969 const TSourceLoc &initLocation,
1970 TIntermTyped *initializer)
Jamie Madill60ed9812013-06-06 11:56:46 -04001971{
Olli Etuahofa33d582015-04-09 14:33:12 +03001972 mDeferredSingleDeclarationErrorCheck = false;
1973
Olli Etuaho383b7912016-08-05 11:22:59 +03001974 singleDeclarationErrorCheck(publicType, identifierLocation);
Jamie Madill60ed9812013-06-06 11:56:46 -04001975
Olli Etuaho13389b62016-10-16 11:48:18 +01001976 TIntermDeclaration *declaration = new TIntermDeclaration();
1977 declaration->setLine(identifierLocation);
1978
1979 TIntermBinary *initNode = nullptr;
1980 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill60ed9812013-06-06 11:56:46 -04001981 {
Olli Etuaho13389b62016-10-16 11:48:18 +01001982 if (initNode)
1983 {
1984 declaration->appendDeclarator(initNode);
1985 }
Jamie Madill60ed9812013-06-06 11:56:46 -04001986 }
Olli Etuaho13389b62016-10-16 11:48:18 +01001987 return declaration;
Jamie Madill60ed9812013-06-06 11:56:46 -04001988}
1989
Olli Etuaho13389b62016-10-16 11:48:18 +01001990TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
Jamie Madillb98c3a82015-07-23 14:26:04 -04001991 TPublicType &publicType,
1992 const TSourceLoc &identifierLocation,
1993 const TString &identifier,
1994 const TSourceLoc &indexLocation,
1995 TIntermTyped *indexExpression,
1996 const TSourceLoc &initLocation,
1997 TIntermTyped *initializer)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03001998{
1999 mDeferredSingleDeclarationErrorCheck = false;
2000
Olli Etuaho383b7912016-08-05 11:22:59 +03002001 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002002
Olli Etuaho8a176262016-08-16 14:23:01 +03002003 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002004
2005 TPublicType arrayType(publicType);
2006
Olli Etuaho856c4972016-08-08 11:38:39 +03002007 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002008 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2009 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002010 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002011 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002012 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002013 }
2014 // Make the type an array even if size check failed.
2015 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2016 arrayType.setArraySize(size);
2017
Olli Etuaho13389b62016-10-16 11:48:18 +01002018 TIntermDeclaration *declaration = new TIntermDeclaration();
2019 declaration->setLine(identifierLocation);
2020
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002021 // initNode will correspond to the whole of "type b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002022 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002023 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2024 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002025 if (initNode)
2026 {
2027 declaration->appendDeclarator(initNode);
2028 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002029 }
Olli Etuaho13389b62016-10-16 11:48:18 +01002030
2031 return declaration;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002032}
2033
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002034TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
Martin Radev70866b82016-07-22 15:27:42 +03002035 const TTypeQualifierBuilder &typeQualifierBuilder,
2036 const TSourceLoc &identifierLoc,
2037 const TString *identifier,
2038 const TSymbol *symbol)
Jamie Madill47e3ec02014-08-20 16:38:33 -04002039{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002040 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002041
Martin Radev70866b82016-07-22 15:27:42 +03002042 if (!typeQualifier.invariant)
2043 {
2044 error(identifierLoc, "Expected invariant", identifier->c_str());
2045 return nullptr;
2046 }
2047 if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
2048 {
2049 return nullptr;
2050 }
Jamie Madill47e3ec02014-08-20 16:38:33 -04002051 if (!symbol)
2052 {
2053 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002054 return nullptr;
Jamie Madill47e3ec02014-08-20 16:38:33 -04002055 }
Martin Radev70866b82016-07-22 15:27:42 +03002056 if (!IsQualifierUnspecified(typeQualifier.qualifier))
Jamie Madill47e3ec02014-08-20 16:38:33 -04002057 {
Martin Radev70866b82016-07-22 15:27:42 +03002058 error(identifierLoc, "invariant declaration specifies qualifier",
2059 getQualifierString(typeQualifier.qualifier));
Jamie Madill47e3ec02014-08-20 16:38:33 -04002060 }
Martin Radev70866b82016-07-22 15:27:42 +03002061 if (typeQualifier.precision != EbpUndefined)
2062 {
2063 error(identifierLoc, "invariant declaration specifies precision",
2064 getPrecisionString(typeQualifier.precision));
2065 }
2066 if (!typeQualifier.layoutQualifier.isEmpty())
2067 {
2068 error(identifierLoc, "invariant declaration specifies layout", "'layout'");
2069 }
2070
2071 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
2072 ASSERT(variable);
2073 const TType &type = variable->getType();
2074
2075 checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
2076 typeQualifier.line);
Martin Radev2cc85b32016-08-05 16:22:53 +03002077 checkIsMemoryQualifierNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
Martin Radev70866b82016-07-22 15:27:42 +03002078
2079 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
2080
2081 TIntermSymbol *intermSymbol =
2082 intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
2083
Olli Etuahobf4e1b72016-12-09 11:30:15 +00002084 return new TIntermInvariantDeclaration(intermSymbol, identifierLoc);
Jamie Madill47e3ec02014-08-20 16:38:33 -04002085}
2086
Olli Etuaho13389b62016-10-16 11:48:18 +01002087void TParseContext::parseDeclarator(TPublicType &publicType,
2088 const TSourceLoc &identifierLocation,
2089 const TString &identifier,
2090 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002091{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002092 // If the declaration starting this declarator list was empty (example: int,), some checks were
2093 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03002094 if (mDeferredSingleDeclarationErrorCheck)
2095 {
Olli Etuaho383b7912016-08-05 11:22:59 +03002096 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03002097 mDeferredSingleDeclarationErrorCheck = false;
2098 }
2099
Olli Etuaho856c4972016-08-08 11:38:39 +03002100 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002101
Olli Etuaho856c4972016-08-08 11:38:39 +03002102 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002103
Olli Etuaho2935c582015-04-08 14:32:06 +03002104 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002105 declareVariable(identifierLocation, identifier, TType(publicType), &variable);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002106
Jamie Madillb98c3a82015-07-23 14:26:04 -04002107 TIntermSymbol *symbol =
2108 intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002109 if (variable && symbol)
Olli Etuaho13389b62016-10-16 11:48:18 +01002110 {
Jamie Madill502d66f2013-06-20 11:55:52 -04002111 symbol->setId(variable->getUniqueId());
Olli Etuaho13389b62016-10-16 11:48:18 +01002112 declarationOut->appendDeclarator(symbol);
2113 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002114}
2115
Olli Etuaho13389b62016-10-16 11:48:18 +01002116void TParseContext::parseArrayDeclarator(TPublicType &publicType,
2117 const TSourceLoc &identifierLocation,
2118 const TString &identifier,
2119 const TSourceLoc &arrayLocation,
2120 TIntermTyped *indexExpression,
2121 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002122{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002123 // If the declaration starting this declarator list was empty (example: int,), some checks were
2124 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03002125 if (mDeferredSingleDeclarationErrorCheck)
2126 {
Olli Etuaho383b7912016-08-05 11:22:59 +03002127 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03002128 mDeferredSingleDeclarationErrorCheck = false;
2129 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002130
Olli Etuaho856c4972016-08-08 11:38:39 +03002131 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002132
Olli Etuaho856c4972016-08-08 11:38:39 +03002133 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
Jamie Madill502d66f2013-06-20 11:55:52 -04002134
Olli Etuaho8a176262016-08-16 14:23:01 +03002135 if (checkIsValidTypeAndQualifierForArray(arrayLocation, publicType))
Jamie Madill502d66f2013-06-20 11:55:52 -04002136 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002137 TType arrayType = TType(publicType);
Olli Etuaho856c4972016-08-08 11:38:39 +03002138 unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
Olli Etuaho693c9aa2015-04-07 17:50:36 +03002139 arrayType.setArraySize(size);
Olli Etuahoe7847b02015-03-16 11:56:12 +02002140
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002141 TVariable *variable = nullptr;
Olli Etuaho383b7912016-08-05 11:22:59 +03002142 declareVariable(identifierLocation, identifier, arrayType, &variable);
Jamie Madill502d66f2013-06-20 11:55:52 -04002143
Jamie Madillb98c3a82015-07-23 14:26:04 -04002144 TIntermSymbol *symbol =
2145 intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002146 if (variable && symbol)
Olli Etuaho6ed7bbe2015-04-07 18:08:46 +03002147 symbol->setId(variable->getUniqueId());
Olli Etuahoe7847b02015-03-16 11:56:12 +02002148
Olli Etuaho13389b62016-10-16 11:48:18 +01002149 declarationOut->appendDeclarator(symbol);
Jamie Madill502d66f2013-06-20 11:55:52 -04002150 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002151}
2152
Olli Etuaho13389b62016-10-16 11:48:18 +01002153void TParseContext::parseInitDeclarator(const TPublicType &publicType,
2154 const TSourceLoc &identifierLocation,
2155 const TString &identifier,
2156 const TSourceLoc &initLocation,
2157 TIntermTyped *initializer,
2158 TIntermDeclaration *declarationOut)
Jamie Madill502d66f2013-06-20 11:55:52 -04002159{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002160 // If the declaration starting this declarator list was empty (example: int,), some checks were
2161 // not performed.
Olli Etuahofa33d582015-04-09 14:33:12 +03002162 if (mDeferredSingleDeclarationErrorCheck)
2163 {
Olli Etuaho383b7912016-08-05 11:22:59 +03002164 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuahofa33d582015-04-09 14:33:12 +03002165 mDeferredSingleDeclarationErrorCheck = false;
2166 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002167
Olli Etuaho856c4972016-08-08 11:38:39 +03002168 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Jamie Madill0bd18df2013-06-20 11:55:52 -04002169
Olli Etuaho13389b62016-10-16 11:48:18 +01002170 TIntermBinary *initNode = nullptr;
2171 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode))
Jamie Madill502d66f2013-06-20 11:55:52 -04002172 {
2173 //
2174 // build the intermediate representation
2175 //
Olli Etuaho13389b62016-10-16 11:48:18 +01002176 if (initNode)
Jamie Madill502d66f2013-06-20 11:55:52 -04002177 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002178 declarationOut->appendDeclarator(initNode);
Jamie Madill502d66f2013-06-20 11:55:52 -04002179 }
Jamie Madill502d66f2013-06-20 11:55:52 -04002180 }
2181}
2182
Olli Etuaho13389b62016-10-16 11:48:18 +01002183void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
2184 const TSourceLoc &identifierLocation,
2185 const TString &identifier,
2186 const TSourceLoc &indexLocation,
2187 TIntermTyped *indexExpression,
2188 const TSourceLoc &initLocation,
2189 TIntermTyped *initializer,
2190 TIntermDeclaration *declarationOut)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002191{
Jamie Madillb98c3a82015-07-23 14:26:04 -04002192 // If the declaration starting this declarator list was empty (example: int,), some checks were
2193 // not performed.
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002194 if (mDeferredSingleDeclarationErrorCheck)
2195 {
Olli Etuaho383b7912016-08-05 11:22:59 +03002196 singleDeclarationErrorCheck(publicType, identifierLocation);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002197 mDeferredSingleDeclarationErrorCheck = false;
2198 }
2199
Olli Etuaho856c4972016-08-08 11:38:39 +03002200 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002201
Olli Etuaho8a176262016-08-16 14:23:01 +03002202 checkIsValidTypeAndQualifierForArray(indexLocation, publicType);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002203
2204 TPublicType arrayType(publicType);
2205
Olli Etuaho856c4972016-08-08 11:38:39 +03002206 unsigned int size = 0u;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002207 // If indexExpression is nullptr, then the array will eventually get its size implicitly from
2208 // the initializer.
Olli Etuaho383b7912016-08-05 11:22:59 +03002209 if (indexExpression != nullptr)
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002210 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002211 size = checkIsValidArraySize(identifierLocation, indexExpression);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002212 }
2213 // Make the type an array even if size check failed.
2214 // This ensures useless error messages regarding the variable's non-arrayness won't follow.
2215 arrayType.setArraySize(size);
2216
2217 // initNode will correspond to the whole of "b[n] = initializer".
Olli Etuaho13389b62016-10-16 11:48:18 +01002218 TIntermBinary *initNode = nullptr;
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002219 if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
2220 {
2221 if (initNode)
2222 {
Olli Etuaho13389b62016-10-16 11:48:18 +01002223 declarationOut->appendDeclarator(initNode);
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002224 }
Olli Etuaho3875ffd2015-04-10 16:45:14 +03002225 }
2226}
2227
Martin Radev70866b82016-07-22 15:27:42 +03002228void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
Jamie Madilla295edf2013-06-06 11:56:48 -04002229{
Olli Etuaho77ba4082016-12-16 12:01:18 +00002230 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madilla295edf2013-06-06 11:56:48 -04002231 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
Jamie Madillc2128ff2016-07-04 10:26:17 -04002232
Martin Radev70866b82016-07-22 15:27:42 +03002233 checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
2234 typeQualifier.line);
2235
Jamie Madillc2128ff2016-07-04 10:26:17 -04002236 // It should never be the case, but some strange parser errors can send us here.
2237 if (layoutQualifier.isEmpty())
2238 {
2239 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
Jamie Madillc2128ff2016-07-04 10:26:17 -04002240 return;
2241 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002242
Martin Radev802abe02016-08-04 17:48:32 +03002243 if (!layoutQualifier.isCombinationValid())
Jamie Madilla295edf2013-06-06 11:56:48 -04002244 {
Martin Radev802abe02016-08-04 17:48:32 +03002245 error(typeQualifier.line, "invalid combination:", "layout");
Jamie Madilla295edf2013-06-06 11:56:48 -04002246 return;
2247 }
2248
Martin Radev2cc85b32016-08-05 16:22:53 +03002249 checkIsMemoryQualifierNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
2250
2251 checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
2252
Martin Radev802abe02016-08-04 17:48:32 +03002253 if (typeQualifier.qualifier == EvqComputeIn)
Jamie Madilla295edf2013-06-06 11:56:48 -04002254 {
Martin Radev802abe02016-08-04 17:48:32 +03002255 if (mComputeShaderLocalSizeDeclared &&
2256 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
2257 {
2258 error(typeQualifier.line, "Work group size does not match the previous declaration",
2259 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002260 return;
2261 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002262
Martin Radev802abe02016-08-04 17:48:32 +03002263 if (mShaderVersion < 310)
2264 {
2265 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002266 return;
2267 }
Jamie Madill099c0f32013-06-20 11:55:52 -04002268
Martin Radev4c4c8e72016-08-04 12:25:34 +03002269 if (!layoutQualifier.localSize.isAnyValueSet())
Martin Radev802abe02016-08-04 17:48:32 +03002270 {
2271 error(typeQualifier.line, "No local work group size specified", "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002272 return;
2273 }
2274
2275 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
2276 symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
2277
2278 const TConstantUnion *maxComputeWorkGroupSizeData =
2279 maxComputeWorkGroupSize->getConstPointer();
2280
2281 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
2282 {
2283 if (layoutQualifier.localSize[i] != -1)
2284 {
2285 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
2286 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
2287 if (mComputeShaderLocalSize[i] < 1 ||
2288 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
2289 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002290 std::stringstream reasonStream;
2291 reasonStream << "invalid value: Value must be at least 1 and no greater than "
2292 << maxComputeWorkGroupSizeValue;
2293 const std::string &reason = reasonStream.str();
Martin Radev802abe02016-08-04 17:48:32 +03002294
Olli Etuaho4de340a2016-12-16 09:32:03 +00002295 error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
Martin Radev802abe02016-08-04 17:48:32 +03002296 return;
2297 }
2298 }
2299 }
2300
2301 mComputeShaderLocalSizeDeclared = true;
2302 }
Olli Etuaho09b04a22016-12-15 13:30:26 +00002303 else if (mMultiviewAvailable &&
2304 (isExtensionEnabled("GL_OVR_multiview") || isExtensionEnabled("GL_OVR_multiview2")) &&
2305 typeQualifier.qualifier == EvqVertexIn)
2306 {
2307 // This error is only specified in WebGL, but tightens unspecified behavior in the native
2308 // specification.
2309 if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
2310 {
2311 error(typeQualifier.line, "Number of views does not match the previous declaration",
2312 "layout");
2313 return;
2314 }
2315
2316 if (layoutQualifier.numViews == -1)
2317 {
2318 error(typeQualifier.line, "No num_views specified", "layout");
2319 return;
2320 }
2321
2322 if (layoutQualifier.numViews > mMaxNumViews)
2323 {
2324 error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
2325 "layout");
2326 return;
2327 }
2328
2329 mNumViews = layoutQualifier.numViews;
2330 }
Martin Radev802abe02016-08-04 17:48:32 +03002331 else
Jamie Madill1566ef72013-06-20 11:55:54 -04002332 {
Olli Etuaho09b04a22016-12-15 13:30:26 +00002333 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
Martin Radev802abe02016-08-04 17:48:32 +03002334 {
Martin Radev802abe02016-08-04 17:48:32 +03002335 return;
2336 }
2337
2338 if (typeQualifier.qualifier != EvqUniform)
2339 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002340 error(typeQualifier.line, "invalid qualifier: global layout must be uniform",
2341 getQualifierString(typeQualifier.qualifier));
Martin Radev802abe02016-08-04 17:48:32 +03002342 return;
2343 }
2344
2345 if (mShaderVersion < 300)
2346 {
2347 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
2348 "layout");
Martin Radev802abe02016-08-04 17:48:32 +03002349 return;
2350 }
2351
Olli Etuaho09b04a22016-12-15 13:30:26 +00002352 checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002353
2354 if (layoutQualifier.matrixPacking != EmpUnspecified)
2355 {
2356 mDefaultMatrixPacking = layoutQualifier.matrixPacking;
2357 }
2358
2359 if (layoutQualifier.blockStorage != EbsUnspecified)
2360 {
2361 mDefaultBlockStorage = layoutQualifier.blockStorage;
2362 }
Jamie Madill1566ef72013-06-20 11:55:54 -04002363 }
Jamie Madilla295edf2013-06-06 11:56:48 -04002364}
2365
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002366TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
2367 const TFunction &function,
2368 const TSourceLoc &location,
2369 bool insertParametersToSymbolTable)
2370{
2371 TIntermFunctionPrototype *prototype = new TIntermFunctionPrototype(function.getReturnType());
2372 // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
2373 // point to the data that already exists in the symbol table.
2374 prototype->getFunctionSymbolInfo()->setFromFunction(function);
2375 prototype->setLine(location);
2376
2377 for (size_t i = 0; i < function.getParamCount(); i++)
2378 {
2379 const TConstParameter &param = function.getParam(i);
2380
2381 // If the parameter has no name, it's not an error, just don't add it to symbol table (could
2382 // be used for unused args).
2383 if (param.name != nullptr)
2384 {
2385 TVariable *variable = new TVariable(param.name, *param.type);
2386
2387 // Insert the parameter in the symbol table.
2388 if (insertParametersToSymbolTable && !symbolTable.declare(variable))
2389 {
2390 error(location, "redefinition", variable->getName().c_str());
2391 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2392 continue;
2393 }
2394 TIntermSymbol *symbol = intermediate.addSymbol(
2395 variable->getUniqueId(), variable->getName(), variable->getType(), location);
2396 prototype->appendParameter(symbol);
2397 }
2398 else
2399 {
2400 prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
2401 }
2402 }
2403 return prototype;
2404}
2405
Olli Etuaho16c745a2017-01-16 17:02:27 +00002406TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
2407 const TFunction &parsedFunction,
2408 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002409{
Olli Etuaho476197f2016-10-11 13:59:08 +01002410 // Note: function found from the symbol table could be the same as parsedFunction if this is the
2411 // first declaration. Either way the instance in the symbol table is used to track whether the
2412 // function is declared multiple times.
2413 TFunction *function = static_cast<TFunction *>(
2414 symbolTable.find(parsedFunction.getMangledName(), getShaderVersion()));
2415 if (function->hasPrototypeDeclaration() && mShaderVersion == 100)
Olli Etuaho5d653182016-01-04 14:43:28 +02002416 {
2417 // ESSL 1.00.17 section 4.2.7.
2418 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
2419 error(location, "duplicate function prototype declarations are not allowed", "function");
Olli Etuaho5d653182016-01-04 14:43:28 +02002420 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002421 function->setHasPrototypeDeclaration();
Olli Etuaho5d653182016-01-04 14:43:28 +02002422
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002423 TIntermFunctionPrototype *prototype =
2424 createPrototypeNodeFromFunction(*function, location, false);
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002425
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002426 symbolTable.pop();
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002427
2428 if (!symbolTable.atGlobalLevel())
2429 {
2430 // ESSL 3.00.4 section 4.2.4.
2431 error(location, "local function prototype declarations are not allowed", "function");
Olli Etuaho8d8b1082016-01-04 16:44:57 +02002432 }
2433
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002434 return prototype;
2435}
2436
Olli Etuaho336b1472016-10-05 16:37:55 +01002437TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002438 TIntermFunctionPrototype *functionPrototype,
Olli Etuaho336b1472016-10-05 16:37:55 +01002439 TIntermBlock *functionBody,
2440 const TSourceLoc &location)
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002441{
Olli Etuahof51fdd22016-10-03 10:03:40 +01002442 // Check that non-void functions have at least one return statement.
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002443 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
2444 {
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002445 error(location, "function does not return a value:",
2446 functionPrototype->getFunctionSymbolInfo()->getName().c_str());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002447 }
2448
Olli Etuahof51fdd22016-10-03 10:03:40 +01002449 if (functionBody == nullptr)
2450 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01002451 functionBody = new TIntermBlock();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002452 functionBody->setLine(location);
2453 }
Olli Etuaho336b1472016-10-05 16:37:55 +01002454 TIntermFunctionDefinition *functionNode =
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002455 new TIntermFunctionDefinition(functionPrototype, functionBody);
Olli Etuaho336b1472016-10-05 16:37:55 +01002456 functionNode->setLine(location);
Olli Etuahof51fdd22016-10-03 10:03:40 +01002457
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002458 symbolTable.pop();
Olli Etuahof51fdd22016-10-03 10:03:40 +01002459 return functionNode;
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002460}
2461
Olli Etuaho476197f2016-10-11 13:59:08 +01002462void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
2463 TFunction **function,
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002464 TIntermFunctionPrototype **prototypeOut)
Jamie Madill185fb402015-06-12 15:48:48 -04002465{
Olli Etuaho476197f2016-10-11 13:59:08 +01002466 ASSERT(function);
2467 ASSERT(*function);
Jamie Madillb98c3a82015-07-23 14:26:04 -04002468 const TSymbol *builtIn =
Olli Etuaho476197f2016-10-11 13:59:08 +01002469 symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002470
2471 if (builtIn)
2472 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002473 error(location, "built-in functions cannot be redefined", (*function)->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002474 }
Olli Etuaho476197f2016-10-11 13:59:08 +01002475 else
Jamie Madill185fb402015-06-12 15:48:48 -04002476 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002477 TFunction *prevDec = static_cast<TFunction *>(
2478 symbolTable.find((*function)->getMangledName(), getShaderVersion()));
2479
2480 // Note: 'prevDec' could be 'function' if this is the first time we've seen function as it
2481 // would have just been put in the symbol table. Otherwise, we're looking up an earlier
2482 // occurance.
2483 if (*function != prevDec)
2484 {
2485 // Swap the parameters of the previous declaration to the parameters of the function
2486 // definition (parameter names may differ).
2487 prevDec->swapParameters(**function);
2488
2489 // The function definition will share the same symbol as any previous declaration.
2490 *function = prevDec;
2491 }
2492
2493 if ((*function)->isDefined())
2494 {
2495 error(location, "function already has a body", (*function)->getName().c_str());
2496 }
2497
2498 (*function)->setDefined();
Jamie Madill185fb402015-06-12 15:48:48 -04002499 }
Jamie Madill185fb402015-06-12 15:48:48 -04002500
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002501 // Remember the return type for later checking for return statements.
Olli Etuaho476197f2016-10-11 13:59:08 +01002502 mCurrentFunctionType = &((*function)->getReturnType());
Olli Etuahoee63f5d2016-01-04 11:34:54 +02002503 mFunctionReturnsValue = false;
Jamie Madill185fb402015-06-12 15:48:48 -04002504
Olli Etuaho8ad9e752017-01-16 19:55:20 +00002505 *prototypeOut = createPrototypeNodeFromFunction(**function, location, true);
Jamie Madill185fb402015-06-12 15:48:48 -04002506 setLoopNestingLevel(0);
2507}
2508
Jamie Madillb98c3a82015-07-23 14:26:04 -04002509TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
Jamie Madill185fb402015-06-12 15:48:48 -04002510{
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002511 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002512 // We don't know at this point whether this is a function definition or a prototype.
2513 // The definition production code will check for redefinitions.
2514 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002515 //
Olli Etuaho5d653182016-01-04 14:43:28 +02002516 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
2517 // here.
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002518 //
2519 TFunction *prevDec =
2520 static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302521
Martin Radevda6254b2016-12-14 17:00:36 +02002522 if (getShaderVersion() >= 300 &&
2523 symbolTable.hasUnmangledBuiltInForShaderVersion(function->getName().c_str(),
2524 getShaderVersion()))
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302525 {
Martin Radevda6254b2016-12-14 17:00:36 +02002526 // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions.
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302527 // Therefore overloading or redefining builtin functions is an error.
2528 error(location, "Name of a built-in function cannot be redeclared as function",
2529 function->getName().c_str());
Olli Etuahoc4a96d62015-07-23 17:37:39 +05302530 }
2531 else if (prevDec)
Jamie Madill185fb402015-06-12 15:48:48 -04002532 {
2533 if (prevDec->getReturnType() != function->getReturnType())
2534 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002535 error(location, "function must have the same return type in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002536 function->getReturnType().getBasicString());
Jamie Madill185fb402015-06-12 15:48:48 -04002537 }
2538 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
2539 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002540 if (prevDec->getParam(i).type->getQualifier() !=
2541 function->getParam(i).type->getQualifier())
Jamie Madill185fb402015-06-12 15:48:48 -04002542 {
Olli Etuaho476197f2016-10-11 13:59:08 +01002543 error(location,
2544 "function must have the same parameter qualifiers in all of its declarations",
Jamie Madill185fb402015-06-12 15:48:48 -04002545 function->getParam(i).type->getQualifierString());
Jamie Madill185fb402015-06-12 15:48:48 -04002546 }
2547 }
2548 }
2549
2550 //
2551 // Check for previously declared variables using the same name.
2552 //
Geoff Lang13e7c7e2015-07-30 14:17:29 +00002553 TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
Jamie Madill185fb402015-06-12 15:48:48 -04002554 if (prevSym)
2555 {
2556 if (!prevSym->isFunction())
2557 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002558 error(location, "redefinition of a function", function->getName().c_str());
Jamie Madill185fb402015-06-12 15:48:48 -04002559 }
2560 }
2561 else
2562 {
2563 // Insert the unmangled name to detect potential future redefinition as a variable.
Olli Etuaho476197f2016-10-11 13:59:08 +01002564 symbolTable.getOuterLevel()->insertUnmangled(function);
Jamie Madill185fb402015-06-12 15:48:48 -04002565 }
2566
2567 // We're at the inner scope level of the function's arguments and body statement.
2568 // Add the function prototype to the surrounding scope instead.
2569 symbolTable.getOuterLevel()->insert(function);
2570
Olli Etuaho78d13742017-01-18 13:06:10 +00002571 // Raise error message if main function takes any parameters or return anything other than void
2572 if (function->getName() == "main")
2573 {
2574 if (function->getParamCount() > 0)
2575 {
2576 error(location, "function cannot take any parameter(s)", "main");
2577 }
2578 if (function->getReturnType().getBasicType() != EbtVoid)
2579 {
2580 error(location, "main function cannot return a value",
2581 function->getReturnType().getBasicString());
2582 }
2583 }
2584
Jamie Madill185fb402015-06-12 15:48:48 -04002585 //
Jamie Madillb98c3a82015-07-23 14:26:04 -04002586 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
2587 // variable names from this one, and not the one that's
Jamie Madill185fb402015-06-12 15:48:48 -04002588 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
2589 //
2590 return function;
2591}
2592
Olli Etuaho9de84a52016-06-14 17:36:01 +03002593TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
2594 const TString *name,
2595 const TSourceLoc &location)
2596{
2597 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
2598 {
2599 error(location, "no qualifiers allowed for function return",
2600 getQualifierString(type.qualifier));
Olli Etuaho9de84a52016-06-14 17:36:01 +03002601 }
2602 if (!type.layoutQualifier.isEmpty())
2603 {
2604 error(location, "no qualifiers allowed for function return", "layout");
Olli Etuaho9de84a52016-06-14 17:36:01 +03002605 }
Martin Radev2cc85b32016-08-05 16:22:53 +03002606 // make sure a sampler or an image is not involved as well...
Martin Radev4a9cd802016-09-01 16:51:51 +03002607 checkIsNotSampler(location, type.typeSpecifierNonArray,
2608 "samplers can't be function return values");
Martin Radev2cc85b32016-08-05 16:22:53 +03002609 checkIsNotImage(location, type.typeSpecifierNonArray, "images can't be function return values");
Olli Etuahoe29324f2016-06-15 10:58:03 +03002610 if (mShaderVersion < 300)
2611 {
2612 // Array return values are forbidden, but there's also no valid syntax for declaring array
2613 // return values in ESSL 1.00.
Olli Etuaho77ba4082016-12-16 12:01:18 +00002614 ASSERT(type.arraySize == 0 || mDiagnostics->numErrors() > 0);
Olli Etuahoe29324f2016-06-15 10:58:03 +03002615
2616 if (type.isStructureContainingArrays())
2617 {
2618 // ESSL 1.00.17 section 6.1 Function Definitions
2619 error(location, "structures containing arrays can't be function return values",
2620 TType(type).getCompleteString().c_str());
Olli Etuahoe29324f2016-06-15 10:58:03 +03002621 }
2622 }
Olli Etuaho9de84a52016-06-14 17:36:01 +03002623
2624 // Add the function as a prototype after parsing it (we do not support recursion)
2625 return new TFunction(name, new TType(type));
2626}
2627
Jamie Madill06145232015-05-13 13:10:01 -04002628TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002629{
Jamie Madill06145232015-05-13 13:10:01 -04002630 TPublicType publicType = publicTypeIn;
Martin Radev4a9cd802016-09-01 16:51:51 +03002631 if (publicType.isStructSpecifier())
Olli Etuahobd163f62015-11-13 12:15:38 +02002632 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002633 error(publicType.getLine(), "constructor can't be a structure definition",
2634 getBasicString(publicType.getBasicType()));
Olli Etuahobd163f62015-11-13 12:15:38 +02002635 }
2636
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002637 TOperator op = EOpNull;
Martin Radev4a9cd802016-09-01 16:51:51 +03002638 if (publicType.getUserDef())
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002639 {
2640 op = EOpConstructStruct;
2641 }
2642 else
2643 {
Geoff Lang156d7192016-07-21 16:11:00 -04002644 op = sh::TypeToConstructorOperator(TType(publicType));
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002645 if (op == EOpNull)
2646 {
Martin Radev4a9cd802016-09-01 16:51:51 +03002647 error(publicType.getLine(), "cannot construct this type",
2648 getBasicString(publicType.getBasicType()));
2649 publicType.setBasicType(EbtFloat);
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002650 op = EOpConstructFloat;
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002651 }
2652 }
2653
Dmitry Skiba7f17a502015-06-22 15:08:39 -07002654 const TType *type = new TType(publicType);
Olli Etuaho72d10202017-01-19 15:58:30 +00002655 return new TFunction(nullptr, type, op);
shannonwoods@chromium.org18851132013-05-30 00:19:54 +00002656}
2657
Jamie Madillb98c3a82015-07-23 14:26:04 -04002658// This function is used to test for the correctness of the parameters passed to various constructor
2659// functions and also convert them to the right datatype if it is allowed and required.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002660//
Olli Etuaho856c4972016-08-08 11:38:39 +03002661// 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 +00002662//
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002663TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
Jamie Madillb98c3a82015-07-23 14:26:04 -04002664 TOperator op,
Olli Etuaho72d10202017-01-19 15:58:30 +00002665 TType type,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302666 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002667{
Olli Etuaho856c4972016-08-08 11:38:39 +03002668 if (type.isUnsizedArray())
2669 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002670 if (arguments->empty())
Olli Etuahobbe9fb52016-11-03 17:16:05 +00002671 {
2672 error(line, "implicitly sized array constructor must have at least one argument", "[]");
2673 type.setArraySize(1u);
2674 return TIntermTyped::CreateZero(type);
2675 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002676 type.setArraySize(static_cast<unsigned int>(arguments->size()));
Olli Etuaho856c4972016-08-08 11:38:39 +03002677 }
Olli Etuaho856c4972016-08-08 11:38:39 +03002678
Olli Etuaho72d10202017-01-19 15:58:30 +00002679 if (!checkConstructorArguments(line, arguments, op, type))
Olli Etuaho856c4972016-08-08 11:38:39 +03002680 {
Olli Etuaho72d10202017-01-19 15:58:30 +00002681 return TIntermTyped::CreateZero(type);
Olli Etuaho856c4972016-08-08 11:38:39 +03002682 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002683
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002684 TIntermAggregate *constructorNode = new TIntermAggregate(type, op, arguments);
2685 constructorNode->setLine(line);
2686 ASSERT(constructorNode->isConstructor());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002687
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002688 TIntermTyped *constConstructor =
2689 intermediate.foldAggregateBuiltIn(constructorNode, mDiagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002690 if (constConstructor)
2691 {
2692 return constConstructor;
2693 }
2694
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08002695 return constructorNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002696}
2697
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002698//
2699// Interface/uniform blocks
2700//
Olli Etuaho13389b62016-10-16 11:48:18 +01002701TIntermDeclaration *TParseContext::addInterfaceBlock(
Martin Radev70866b82016-07-22 15:27:42 +03002702 const TTypeQualifierBuilder &typeQualifierBuilder,
2703 const TSourceLoc &nameLine,
2704 const TString &blockName,
2705 TFieldList *fieldList,
2706 const TString *instanceName,
2707 const TSourceLoc &instanceLine,
2708 TIntermTyped *arrayIndex,
2709 const TSourceLoc &arrayIndexLine)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002710{
Olli Etuaho856c4972016-08-08 11:38:39 +03002711 checkIsNotReserved(nameLine, blockName);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002712
Olli Etuaho77ba4082016-12-16 12:01:18 +00002713 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Martin Radev70866b82016-07-22 15:27:42 +03002714
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002715 if (typeQualifier.qualifier != EvqUniform)
2716 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002717 error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform",
2718 getQualifierString(typeQualifier.qualifier));
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002719 }
2720
Martin Radev70866b82016-07-22 15:27:42 +03002721 if (typeQualifier.invariant)
2722 {
2723 error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
2724 }
2725
Martin Radev2cc85b32016-08-05 16:22:53 +03002726 checkIsMemoryQualifierNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
2727
Jamie Madill099c0f32013-06-20 11:55:52 -04002728 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
Olli Etuaho856c4972016-08-08 11:38:39 +03002729 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04002730
Jamie Madill099c0f32013-06-20 11:55:52 -04002731 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
2732 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002733 blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002734 }
2735
Jamie Madill1566ef72013-06-20 11:55:54 -04002736 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
2737 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002738 blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
Jamie Madill1566ef72013-06-20 11:55:54 -04002739 }
2740
Olli Etuaho856c4972016-08-08 11:38:39 +03002741 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03002742
Martin Radev2cc85b32016-08-05 16:22:53 +03002743 checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
2744
Arun Patole7e7e68d2015-05-22 12:02:25 +05302745 TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
2746 if (!symbolTable.declare(blockNameSymbol))
2747 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002748 error(nameLine, "redefinition of an interface block name", blockName.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002749 }
2750
Jamie Madill98493dd2013-07-08 14:39:03 -04002751 // check for sampler types and apply layout qualifiers
Arun Patole7e7e68d2015-05-22 12:02:25 +05302752 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2753 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002754 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302755 TType *fieldType = field->type();
2756 if (IsSampler(fieldType->getBasicType()))
2757 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002758 error(field->line(),
2759 "unsupported type - sampler types are not allowed in interface blocks",
2760 fieldType->getBasicString());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002761 }
2762
Martin Radev2cc85b32016-08-05 16:22:53 +03002763 if (IsImage(fieldType->getBasicType()))
2764 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002765 error(field->line(),
2766 "unsupported type - image types are not allowed in interface blocks",
2767 fieldType->getBasicString());
Martin Radev2cc85b32016-08-05 16:22:53 +03002768 }
2769
Jamie Madill98493dd2013-07-08 14:39:03 -04002770 const TQualifier qualifier = fieldType->getQualifier();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002771 switch (qualifier)
2772 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002773 case EvqGlobal:
2774 case EvqUniform:
2775 break;
2776 default:
2777 error(field->line(), "invalid qualifier on interface block member",
2778 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04002779 break;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002780 }
Jamie Madilla5efff92013-06-06 11:56:47 -04002781
Martin Radev70866b82016-07-22 15:27:42 +03002782 if (fieldType->isInvariant())
2783 {
2784 error(field->line(), "invalid qualifier on interface block member", "invariant");
2785 }
2786
Jamie Madilla5efff92013-06-06 11:56:47 -04002787 // check layout qualifiers
Jamie Madill98493dd2013-07-08 14:39:03 -04002788 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
Olli Etuaho856c4972016-08-08 11:38:39 +03002789 checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
Jamie Madill099c0f32013-06-20 11:55:52 -04002790
Jamie Madill98493dd2013-07-08 14:39:03 -04002791 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
Jamie Madill1566ef72013-06-20 11:55:54 -04002792 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002793 error(field->line(), "invalid layout qualifier: cannot be used here",
2794 getBlockStorageString(fieldLayoutQualifier.blockStorage));
Jamie Madill1566ef72013-06-20 11:55:54 -04002795 }
2796
Jamie Madill98493dd2013-07-08 14:39:03 -04002797 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
Jamie Madill099c0f32013-06-20 11:55:52 -04002798 {
Jamie Madill98493dd2013-07-08 14:39:03 -04002799 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
Jamie Madill099c0f32013-06-20 11:55:52 -04002800 }
Olli Etuahofb6ab2c2015-07-09 20:55:28 +03002801 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
Jamie Madill099c0f32013-06-20 11:55:52 -04002802 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002803 warning(field->line(),
2804 "extraneous layout qualifier: only has an effect on matrix types",
2805 getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
Jamie Madill099c0f32013-06-20 11:55:52 -04002806 }
2807
Jamie Madill98493dd2013-07-08 14:39:03 -04002808 fieldType->setLayoutQualifier(fieldLayoutQualifier);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002809 }
2810
Jamie Madill98493dd2013-07-08 14:39:03 -04002811 // add array index
Olli Etuaho856c4972016-08-08 11:38:39 +03002812 unsigned int arraySize = 0;
2813 if (arrayIndex != nullptr)
Jamie Madill98493dd2013-07-08 14:39:03 -04002814 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002815 arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
Jamie Madill98493dd2013-07-08 14:39:03 -04002816 }
2817
Jamie Madillb98c3a82015-07-23 14:26:04 -04002818 TInterfaceBlock *interfaceBlock =
2819 new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
2820 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
2821 arraySize);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002822
2823 TString symbolName = "";
Jamie Madillb98c3a82015-07-23 14:26:04 -04002824 int symbolId = 0;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002825
Jamie Madill98493dd2013-07-08 14:39:03 -04002826 if (!instanceName)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002827 {
2828 // define symbols for the members of the interface block
Jamie Madill98493dd2013-07-08 14:39:03 -04002829 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
2830 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04002831 TField *field = (*fieldList)[memberIndex];
Arun Patole7e7e68d2015-05-22 12:02:25 +05302832 TType *fieldType = field->type();
Jamie Madill98493dd2013-07-08 14:39:03 -04002833
2834 // set parent pointer of the field variable
2835 fieldType->setInterfaceBlock(interfaceBlock);
2836
Arun Patole7e7e68d2015-05-22 12:02:25 +05302837 TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
Jamie Madill98493dd2013-07-08 14:39:03 -04002838 fieldVariable->setQualifier(typeQualifier.qualifier);
2839
Arun Patole7e7e68d2015-05-22 12:02:25 +05302840 if (!symbolTable.declare(fieldVariable))
2841 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002842 error(field->line(), "redefinition of an interface block member name",
2843 field->name().c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002844 }
2845 }
2846 }
2847 else
2848 {
Olli Etuaho856c4972016-08-08 11:38:39 +03002849 checkIsNotReserved(instanceLine, *instanceName);
Olli Etuahoe0f623a2015-07-10 11:58:30 +03002850
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002851 // add a symbol for this interface block
Arun Patole7e7e68d2015-05-22 12:02:25 +05302852 TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002853 instanceTypeDef->setQualifier(typeQualifier.qualifier);
Jamie Madill98493dd2013-07-08 14:39:03 -04002854
Arun Patole7e7e68d2015-05-22 12:02:25 +05302855 if (!symbolTable.declare(instanceTypeDef))
2856 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002857 error(instanceLine, "redefinition of an interface block instance name",
2858 instanceName->c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002859 }
2860
Jamie Madillb98c3a82015-07-23 14:26:04 -04002861 symbolId = instanceTypeDef->getUniqueId();
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002862 symbolName = instanceTypeDef->getName();
2863 }
2864
Olli Etuaho13389b62016-10-16 11:48:18 +01002865 TIntermSymbol *blockSymbol =
2866 intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line);
2867 TIntermDeclaration *declaration = new TIntermDeclaration();
2868 declaration->appendDeclarator(blockSymbol);
2869 declaration->setLine(nameLine);
Jamie Madill98493dd2013-07-08 14:39:03 -04002870
2871 exitStructDeclaration();
Olli Etuaho13389b62016-10-16 11:48:18 +01002872 return declaration;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00002873}
2874
Olli Etuaho383b7912016-08-05 11:22:59 +03002875void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002876{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002877 ++mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002878
2879 // Embedded structure definitions are not supported per GLSL ES spec.
Olli Etuaho4de340a2016-12-16 09:32:03 +00002880 // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302881 if (mStructNestingLevel > 1)
2882 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002883 error(line, "Embedded struct definitions are not allowed", "struct");
kbr@chromium.org476541f2011-10-27 21:14:51 +00002884 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002885}
2886
2887void TParseContext::exitStructDeclaration()
2888{
Jamie Madill6e06b1f2015-05-14 10:01:17 -04002889 --mStructNestingLevel;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002890}
2891
Olli Etuaho8a176262016-08-16 14:23:01 +03002892void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
kbr@chromium.org476541f2011-10-27 21:14:51 +00002893{
Jamie Madillacb4b812016-11-07 13:50:29 -05002894 if (!sh::IsWebGLBasedSpec(mShaderSpec))
Arun Patole7e7e68d2015-05-22 12:02:25 +05302895 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002896 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002897 }
2898
Arun Patole7e7e68d2015-05-22 12:02:25 +05302899 if (field.type()->getBasicType() != EbtStruct)
2900 {
Olli Etuaho8a176262016-08-16 14:23:01 +03002901 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002902 }
2903
2904 // We're already inside a structure definition at this point, so add
2905 // one to the field's struct nesting.
Arun Patole7e7e68d2015-05-22 12:02:25 +05302906 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2907 {
Jamie Madill41a49272014-03-18 16:10:13 -04002908 std::stringstream reasonStream;
Jamie Madillb98c3a82015-07-23 14:26:04 -04002909 reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
2910 << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
Jamie Madill41a49272014-03-18 16:10:13 -04002911 std::string reason = reasonStream.str();
Olli Etuaho4de340a2016-12-16 09:32:03 +00002912 error(line, reason.c_str(), field.name().c_str());
Olli Etuaho8a176262016-08-16 14:23:01 +03002913 return;
kbr@chromium.org476541f2011-10-27 21:14:51 +00002914 }
kbr@chromium.org476541f2011-10-27 21:14:51 +00002915}
2916
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00002917//
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002918// Parse an array index expression
2919//
Jamie Madillb98c3a82015-07-23 14:26:04 -04002920TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
2921 const TSourceLoc &location,
Arun Patole7e7e68d2015-05-22 12:02:25 +05302922 TIntermTyped *indexExpression)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002923{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002924 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
2925 {
2926 if (baseExpression->getAsSymbolNode())
2927 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05302928 error(location, " left of '[' is not of type array, matrix, or vector ",
2929 baseExpression->getAsSymbolNode()->getSymbol().c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002930 }
2931 else
2932 {
2933 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2934 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002935
2936 TConstantUnion *unionArray = new TConstantUnion[1];
2937 unionArray->setFConst(0.0f);
2938 return intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst),
2939 location);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00002940 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00002941
Jamie Madill21c1e452014-12-29 11:33:41 -05002942 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2943
Olli Etuaho36b05142015-11-12 13:10:42 +02002944 // TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
2945 // to constant fold all constant expressions. Right now we don't allow indexing interface blocks
2946 // or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
2947 // index is a constant expression.
2948 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
2949 {
2950 if (baseExpression->isInterfaceBlock())
2951 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002952 error(location,
2953 "array indexes for interface blocks arrays must be constant integral expressions",
2954 "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02002955 }
2956 else if (baseExpression->getQualifier() == EvqFragmentOut)
2957 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002958 error(location,
2959 "array indexes for fragment outputs must be constant integral expressions", "[");
Olli Etuaho36b05142015-11-12 13:10:42 +02002960 }
Olli Etuaho3e960462015-11-12 15:58:39 +02002961 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
2962 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002963 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3e960462015-11-12 15:58:39 +02002964 }
Olli Etuaho36b05142015-11-12 13:10:42 +02002965 }
2966
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002967 if (indexConstantUnion)
Jamie Madill7164cf42013-07-08 13:30:59 -04002968 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002969 // If an out-of-range index is not qualified as constant, the behavior in the spec is
2970 // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
2971 // constant fold expressions that are not constant expressions). The most compatible way to
2972 // handle this case is to report a warning instead of an error and force the index to be in
2973 // the correct range.
Olli Etuaho7c3848e2015-11-04 13:19:17 +02002974 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002975 int index = indexConstantUnion->getIConst(0);
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002976
2977 int safeIndex = -1;
2978
2979 if (baseExpression->isArray())
Jamie Madill7164cf42013-07-08 13:30:59 -04002980 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002981 if (baseExpression->getQualifier() == EvqFragData && index > 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03002982 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002983 if (mShaderSpec == SH_WEBGL2_SPEC)
2984 {
2985 // Error has been already generated if index is not const.
2986 if (indexExpression->getQualifier() == EvqConst)
2987 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002988 error(location, "array index for gl_FragData must be constant zero", "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002989 }
2990 safeIndex = 0;
2991 }
2992 else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
2993 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00002994 outOfRangeError(outOfRangeIndexIsError, location,
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002995 "array index for gl_FragData must be zero when "
Olli Etuaho4de340a2016-12-16 09:32:03 +00002996 "GL_EXT_draw_buffers is disabled",
2997 "[");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03002998 safeIndex = 0;
2999 }
Olli Etuaho90892fb2016-07-14 14:44:51 +03003000 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003001 // Only do generic out-of-range check if similar error hasn't already been reported.
3002 if (safeIndex < 0)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003003 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003004 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3005 baseExpression->getArraySize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003006 "array index out of range");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003007 }
3008 }
3009 else if (baseExpression->isMatrix())
3010 {
3011 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
Olli Etuaho90892fb2016-07-14 14:44:51 +03003012 baseExpression->getType().getCols(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003013 "matrix field selection out of range");
Jamie Madill7164cf42013-07-08 13:30:59 -04003014 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003015 else if (baseExpression->isVector())
Jamie Madill7164cf42013-07-08 13:30:59 -04003016 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003017 safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
3018 baseExpression->getType().getNominalSize(),
Olli Etuaho4de340a2016-12-16 09:32:03 +00003019 "vector field selection out of range");
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003020 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003021
3022 ASSERT(safeIndex >= 0);
3023 // Data of constant unions can't be changed, because it may be shared with other
3024 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
3025 // sanitized object.
3026 if (safeIndex != index)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003027 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003028 TConstantUnion *safeConstantUnion = new TConstantUnion();
3029 safeConstantUnion->setIConst(safeIndex);
3030 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003031 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003032
3033 return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003034 mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003035 }
Jamie Madill7164cf42013-07-08 13:30:59 -04003036 else
3037 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003038 return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003039 mDiagnostics);
Jamie Madill7164cf42013-07-08 13:30:59 -04003040 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003041}
3042
Olli Etuaho90892fb2016-07-14 14:44:51 +03003043int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
3044 const TSourceLoc &location,
3045 int index,
3046 int arraySize,
Olli Etuaho4de340a2016-12-16 09:32:03 +00003047 const char *reason)
Olli Etuaho90892fb2016-07-14 14:44:51 +03003048{
3049 if (index >= arraySize || index < 0)
3050 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003051 std::stringstream reasonStream;
3052 reasonStream << reason << " '" << index << "'";
3053 std::string token = reasonStream.str();
3054 outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
Olli Etuaho90892fb2016-07-14 14:44:51 +03003055 if (index < 0)
3056 {
3057 return 0;
3058 }
3059 else
3060 {
3061 return arraySize - 1;
3062 }
3063 }
3064 return index;
3065}
3066
Jamie Madillb98c3a82015-07-23 14:26:04 -04003067TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
3068 const TSourceLoc &dotLocation,
3069 const TString &fieldString,
3070 const TSourceLoc &fieldLocation)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003071{
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003072 if (baseExpression->isArray())
3073 {
3074 error(fieldLocation, "cannot apply dot operator to an array", ".");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003075 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003076 }
3077
3078 if (baseExpression->isVector())
3079 {
3080 TVectorFields fields;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003081 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
3082 fieldLocation))
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003083 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003084 fields.num = 1;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003085 fields.offsets[0] = 0;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003086 }
3087
Olli Etuahob6fa0432016-09-28 16:28:05 +01003088 return TIntermediate::AddSwizzle(baseExpression, fields, dotLocation);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003089 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003090 else if (baseExpression->getBasicType() == EbtStruct)
3091 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303092 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003093 if (fields.empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003094 {
3095 error(dotLocation, "structure has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003096 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003097 }
3098 else
3099 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003100 bool fieldFound = false;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003101 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003102 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003103 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003104 if (fields[i]->name() == fieldString)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003105 {
3106 fieldFound = true;
3107 break;
3108 }
3109 }
3110 if (fieldFound)
3111 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003112 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3113 index->setLine(fieldLocation);
3114 return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003115 dotLocation, mDiagnostics);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003116 }
3117 else
3118 {
3119 error(dotLocation, " no such field in structure", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003120 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003121 }
3122 }
3123 }
Jamie Madill98493dd2013-07-08 14:39:03 -04003124 else if (baseExpression->isInterfaceBlock())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003125 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303126 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04003127 if (fields.empty())
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003128 {
3129 error(dotLocation, "interface block has no fields", "Internal Error");
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003130 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003131 }
3132 else
3133 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003134 bool fieldFound = false;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003135 unsigned int i;
Jamie Madill98493dd2013-07-08 14:39:03 -04003136 for (i = 0; i < fields.size(); ++i)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003137 {
Jamie Madill98493dd2013-07-08 14:39:03 -04003138 if (fields[i]->name() == fieldString)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003139 {
3140 fieldFound = true;
3141 break;
3142 }
3143 }
3144 if (fieldFound)
3145 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003146 TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
3147 index->setLine(fieldLocation);
3148 return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003149 dotLocation, mDiagnostics);
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003150 }
3151 else
3152 {
3153 error(dotLocation, " no such field in interface block", fieldString.c_str());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003154 return baseExpression;
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003155 }
3156 }
3157 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003158 else
3159 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003160 if (mShaderVersion < 300)
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003161 {
Olli Etuaho56193ce2015-08-12 15:55:09 +03003162 error(dotLocation, " field selection requires structure or vector on left hand side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303163 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003164 }
3165 else
3166 {
Arun Patole7e7e68d2015-05-22 12:02:25 +05303167 error(dotLocation,
Olli Etuaho56193ce2015-08-12 15:55:09 +03003168 " field selection requires structure, vector, or interface block on left hand "
3169 "side",
Arun Patole7e7e68d2015-05-22 12:02:25 +05303170 fieldString.c_str());
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +00003171 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03003172 return baseExpression;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003173 }
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003174}
3175
Jamie Madillb98c3a82015-07-23 14:26:04 -04003176TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3177 const TSourceLoc &qualifierTypeLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003178{
Martin Radev802abe02016-08-04 17:48:32 +03003179 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003180
3181 if (qualifierType == "shared")
3182 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003183 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003184 {
3185 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
3186 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003187 qualifier.blockStorage = EbsShared;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003188 }
3189 else if (qualifierType == "packed")
3190 {
Jamie Madillacb4b812016-11-07 13:50:29 -05003191 if (sh::IsWebGLBasedSpec(mShaderSpec))
Olli Etuahof0173152016-10-17 09:05:03 -07003192 {
3193 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
3194 }
Jamie Madilla5efff92013-06-06 11:56:47 -04003195 qualifier.blockStorage = EbsPacked;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003196 }
3197 else if (qualifierType == "std140")
3198 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003199 qualifier.blockStorage = EbsStd140;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003200 }
3201 else if (qualifierType == "row_major")
3202 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003203 qualifier.matrixPacking = EmpRowMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003204 }
3205 else if (qualifierType == "column_major")
3206 {
Jamie Madilla5efff92013-06-06 11:56:47 -04003207 qualifier.matrixPacking = EmpColumnMajor;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003208 }
3209 else if (qualifierType == "location")
3210 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003211 error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
3212 qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003213 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003214 else if (qualifierType == "rgba32f")
3215 {
3216 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3217 qualifier.imageInternalFormat = EiifRGBA32F;
3218 }
3219 else if (qualifierType == "rgba16f")
3220 {
3221 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3222 qualifier.imageInternalFormat = EiifRGBA16F;
3223 }
3224 else if (qualifierType == "r32f")
3225 {
3226 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3227 qualifier.imageInternalFormat = EiifR32F;
3228 }
3229 else if (qualifierType == "rgba8")
3230 {
3231 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3232 qualifier.imageInternalFormat = EiifRGBA8;
3233 }
3234 else if (qualifierType == "rgba8_snorm")
3235 {
3236 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3237 qualifier.imageInternalFormat = EiifRGBA8_SNORM;
3238 }
3239 else if (qualifierType == "rgba32i")
3240 {
3241 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3242 qualifier.imageInternalFormat = EiifRGBA32I;
3243 }
3244 else if (qualifierType == "rgba16i")
3245 {
3246 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3247 qualifier.imageInternalFormat = EiifRGBA16I;
3248 }
3249 else if (qualifierType == "rgba8i")
3250 {
3251 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3252 qualifier.imageInternalFormat = EiifRGBA8I;
3253 }
3254 else if (qualifierType == "r32i")
3255 {
3256 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3257 qualifier.imageInternalFormat = EiifR32I;
3258 }
3259 else if (qualifierType == "rgba32ui")
3260 {
3261 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3262 qualifier.imageInternalFormat = EiifRGBA32UI;
3263 }
3264 else if (qualifierType == "rgba16ui")
3265 {
3266 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3267 qualifier.imageInternalFormat = EiifRGBA16UI;
3268 }
3269 else if (qualifierType == "rgba8ui")
3270 {
3271 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3272 qualifier.imageInternalFormat = EiifRGBA8UI;
3273 }
3274 else if (qualifierType == "r32ui")
3275 {
3276 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
3277 qualifier.imageInternalFormat = EiifR32UI;
3278 }
3279
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003280 else
3281 {
3282 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003283 }
3284
Jamie Madilla5efff92013-06-06 11:56:47 -04003285 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003286}
3287
Martin Radev802abe02016-08-04 17:48:32 +03003288void TParseContext::parseLocalSize(const TString &qualifierType,
3289 const TSourceLoc &qualifierTypeLine,
3290 int intValue,
3291 const TSourceLoc &intValueLine,
3292 const std::string &intValueString,
3293 size_t index,
Martin Radev4c4c8e72016-08-04 12:25:34 +03003294 sh::WorkGroupSize *localSize)
Martin Radev802abe02016-08-04 17:48:32 +03003295{
Olli Etuaho856c4972016-08-08 11:38:39 +03003296 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
Martin Radev802abe02016-08-04 17:48:32 +03003297 if (intValue < 1)
3298 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003299 std::stringstream reasonStream;
3300 reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
3301 std::string reason = reasonStream.str();
3302 error(intValueLine, reason.c_str(), intValueString.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003303 }
3304 (*localSize)[index] = intValue;
3305}
3306
Olli Etuaho09b04a22016-12-15 13:30:26 +00003307void TParseContext::parseNumViews(int intValue,
3308 const TSourceLoc &intValueLine,
3309 const std::string &intValueString,
3310 int *numViews)
3311{
3312 // This error is only specified in WebGL, but tightens unspecified behavior in the native
3313 // specification.
3314 if (intValue < 1)
3315 {
3316 error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
3317 }
3318 *numViews = intValue;
3319}
3320
Jamie Madillb98c3a82015-07-23 14:26:04 -04003321TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
3322 const TSourceLoc &qualifierTypeLine,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003323 int intValue,
Arun Patole7e7e68d2015-05-22 12:02:25 +05303324 const TSourceLoc &intValueLine)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003325{
Martin Radev802abe02016-08-04 17:48:32 +03003326 TLayoutQualifier qualifier = TLayoutQualifier::create();
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003327
Martin Radev802abe02016-08-04 17:48:32 +03003328 std::string intValueString = Str(intValue);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003329
Martin Radev802abe02016-08-04 17:48:32 +03003330 if (qualifierType == "location")
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003331 {
Jamie Madill05a80ce2013-06-20 11:55:49 -04003332 // must check that location is non-negative
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003333 if (intValue < 0)
3334 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003335 error(intValueLine, "out of range: location must be non-negative",
3336 intValueString.c_str());
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003337 }
3338 else
3339 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05003340 qualifier.location = intValue;
Olli Etuaho87d410c2016-09-05 13:33:26 +03003341 qualifier.locationsSpecified = 1;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003342 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003343 }
Martin Radev802abe02016-08-04 17:48:32 +03003344 else if (qualifierType == "local_size_x")
3345 {
3346 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
3347 &qualifier.localSize);
3348 }
3349 else if (qualifierType == "local_size_y")
3350 {
3351 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
3352 &qualifier.localSize);
3353 }
3354 else if (qualifierType == "local_size_z")
3355 {
3356 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
3357 &qualifier.localSize);
3358 }
Olli Etuaho09b04a22016-12-15 13:30:26 +00003359 else if (qualifierType == "num_views" && mMultiviewAvailable &&
3360 (isExtensionEnabled("GL_OVR_multiview") || isExtensionEnabled("GL_OVR_multiview2")) &&
3361 mShaderType == GL_VERTEX_SHADER)
3362 {
3363 parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
3364 }
Martin Radev802abe02016-08-04 17:48:32 +03003365 else
3366 {
3367 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
Martin Radev802abe02016-08-04 17:48:32 +03003368 }
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003369
Jamie Madilla5efff92013-06-06 11:56:47 -04003370 return qualifier;
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003371}
3372
Olli Etuaho613b9592016-09-05 12:05:53 +03003373TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
3374{
3375 return new TTypeQualifierBuilder(
3376 new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
3377 mShaderVersion);
3378}
3379
Jamie Madillb98c3a82015-07-23 14:26:04 -04003380TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
Martin Radev802abe02016-08-04 17:48:32 +03003381 TLayoutQualifier rightQualifier,
3382 const TSourceLoc &rightQualifierLocation)
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003383{
Martin Radevc28888b2016-07-22 15:27:42 +03003384 return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
Olli Etuaho77ba4082016-12-16 12:01:18 +00003385 mDiagnostics);
shannonwoods@chromium.org302adfe2013-05-30 00:21:06 +00003386}
3387
Olli Etuaho4de340a2016-12-16 09:32:03 +00003388TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
3389 const TFieldList *newlyAddedFields,
3390 const TSourceLoc &location)
3391{
3392 for (TField *field : *newlyAddedFields)
3393 {
3394 for (TField *oldField : *processedFields)
3395 {
3396 if (oldField->name() == field->name())
3397 {
3398 error(location, "duplicate field name in structure", field->name().c_str());
3399 }
3400 }
3401 processedFields->push_back(field);
3402 }
3403 return processedFields;
3404}
3405
Martin Radev70866b82016-07-22 15:27:42 +03003406TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
3407 const TTypeQualifierBuilder &typeQualifierBuilder,
3408 TPublicType *typeSpecifier,
3409 TFieldList *fieldList)
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003410{
Olli Etuaho77ba4082016-12-16 12:01:18 +00003411 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003412
Martin Radev70866b82016-07-22 15:27:42 +03003413 typeSpecifier->qualifier = typeQualifier.qualifier;
3414 typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
Martin Radev2cc85b32016-08-05 16:22:53 +03003415 typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
Martin Radev70866b82016-07-22 15:27:42 +03003416 typeSpecifier->invariant = typeQualifier.invariant;
3417 if (typeQualifier.precision != EbpUndefined)
Arun Patole7e7e68d2015-05-22 12:02:25 +05303418 {
Martin Radev70866b82016-07-22 15:27:42 +03003419 typeSpecifier->precision = typeQualifier.precision;
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003420 }
Martin Radev70866b82016-07-22 15:27:42 +03003421 return addStructDeclaratorList(*typeSpecifier, fieldList);
Jamie Madillf2e0f9b2013-08-26 16:39:42 -04003422}
3423
Jamie Madillb98c3a82015-07-23 14:26:04 -04003424TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
3425 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003426{
Martin Radev4a9cd802016-09-01 16:51:51 +03003427 checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
3428 typeSpecifier.getBasicType());
Martin Radev70866b82016-07-22 15:27:42 +03003429
Martin Radev4a9cd802016-09-01 16:51:51 +03003430 checkIsNonVoid(typeSpecifier.getLine(), (*fieldList)[0]->name(), typeSpecifier.getBasicType());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003431
Martin Radev4a9cd802016-09-01 16:51:51 +03003432 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
Martin Radev802abe02016-08-04 17:48:32 +03003433
Arun Patole7e7e68d2015-05-22 12:02:25 +05303434 for (unsigned int i = 0; i < fieldList->size(); ++i)
3435 {
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003436 //
3437 // Careful not to replace already known aspects of type, like array-ness
3438 //
Arun Patole7e7e68d2015-05-22 12:02:25 +05303439 TType *type = (*fieldList)[i]->type();
Martin Radev4a9cd802016-09-01 16:51:51 +03003440 type->setBasicType(typeSpecifier.getBasicType());
3441 type->setPrimarySize(typeSpecifier.getPrimarySize());
3442 type->setSecondarySize(typeSpecifier.getSecondarySize());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003443 type->setPrecision(typeSpecifier.precision);
3444 type->setQualifier(typeSpecifier.qualifier);
Jamie Madilla5efff92013-06-06 11:56:47 -04003445 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
Martin Radev2cc85b32016-08-05 16:22:53 +03003446 type->setMemoryQualifier(typeSpecifier.memoryQualifier);
Martin Radev70866b82016-07-22 15:27:42 +03003447 type->setInvariant(typeSpecifier.invariant);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003448
3449 // don't allow arrays of arrays
Arun Patole7e7e68d2015-05-22 12:02:25 +05303450 if (type->isArray())
3451 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003452 checkIsValidTypeForArray(typeSpecifier.getLine(), typeSpecifier);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003453 }
3454 if (typeSpecifier.array)
Olli Etuaho856c4972016-08-08 11:38:39 +03003455 type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
Martin Radev4a9cd802016-09-01 16:51:51 +03003456 if (typeSpecifier.getUserDef())
Arun Patole7e7e68d2015-05-22 12:02:25 +05303457 {
Martin Radev4a9cd802016-09-01 16:51:51 +03003458 type->setStruct(typeSpecifier.getUserDef()->getStruct());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003459 }
3460
Martin Radev4a9cd802016-09-01 16:51:51 +03003461 checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003462 }
3463
Jamie Madill98493dd2013-07-08 14:39:03 -04003464 return fieldList;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003465}
3466
Martin Radev4a9cd802016-09-01 16:51:51 +03003467TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
3468 const TSourceLoc &nameLine,
3469 const TString *structName,
3470 TFieldList *fieldList)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003471{
Arun Patole7e7e68d2015-05-22 12:02:25 +05303472 TStructure *structure = new TStructure(structName, fieldList);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003473 TType *structureType = new TType(structure);
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003474
Jamie Madill9b820842015-02-12 10:40:10 -05003475 // Store a bool in the struct if we're at global scope, to allow us to
3476 // skip the local struct scoping workaround in HLSL.
Jamie Madill9b820842015-02-12 10:40:10 -05003477 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
Jamie Madillbfa91f42014-06-05 15:45:18 -04003478
Jamie Madill98493dd2013-07-08 14:39:03 -04003479 if (!structName->empty())
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003480 {
Olli Etuaho856c4972016-08-08 11:38:39 +03003481 checkIsNotReserved(nameLine, *structName);
Arun Patole7e7e68d2015-05-22 12:02:25 +05303482 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
3483 if (!symbolTable.declare(userTypeDef))
3484 {
Olli Etuaho4de340a2016-12-16 09:32:03 +00003485 error(nameLine, "redefinition of a struct", structName->c_str());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003486 }
3487 }
3488
3489 // ensure we do not specify any storage qualifiers on the struct members
Jamie Madill98493dd2013-07-08 14:39:03 -04003490 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003491 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003492 const TField &field = *(*fieldList)[typeListIndex];
Jamie Madill98493dd2013-07-08 14:39:03 -04003493 const TQualifier qualifier = field.type()->getQualifier();
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003494 switch (qualifier)
3495 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003496 case EvqGlobal:
3497 case EvqTemporary:
3498 break;
3499 default:
3500 error(field.line(), "invalid qualifier on struct member",
3501 getQualifierString(qualifier));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003502 break;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003503 }
Martin Radev70866b82016-07-22 15:27:42 +03003504 if (field.type()->isInvariant())
3505 {
3506 error(field.line(), "invalid qualifier on struct member", "invariant");
3507 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003508 if (IsImage(field.type()->getBasicType()))
3509 {
3510 error(field.line(), "disallowed type in struct", field.type()->getBasicString());
3511 }
3512
3513 checkIsMemoryQualifierNotSpecified(field.type()->getMemoryQualifier(), field.line());
Martin Radev70866b82016-07-22 15:27:42 +03003514
3515 checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003516 }
3517
Martin Radev4a9cd802016-09-01 16:51:51 +03003518 TTypeSpecifierNonArray typeSpecifierNonArray;
3519 typeSpecifierNonArray.initialize(EbtStruct, structLine);
3520 typeSpecifierNonArray.userDef = structureType;
3521 typeSpecifierNonArray.isStructSpecifier = true;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003522 exitStructDeclaration();
3523
Martin Radev4a9cd802016-09-01 16:51:51 +03003524 return typeSpecifierNonArray;
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00003525}
3526
Jamie Madillb98c3a82015-07-23 14:26:04 -04003527TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01003528 TIntermBlock *statementList,
Jamie Madillb98c3a82015-07-23 14:26:04 -04003529 const TSourceLoc &loc)
Olli Etuahoa3a36662015-02-17 13:46:51 +02003530{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003531 TBasicType switchType = init->getBasicType();
Jamie Madillb98c3a82015-07-23 14:26:04 -04003532 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
Olli Etuaho53f076f2015-02-20 10:55:14 +02003533 init->isVector())
3534 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003535 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
3536 "switch");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003537 return nullptr;
3538 }
3539
Olli Etuahoac5274d2015-02-20 10:19:08 +02003540 if (statementList)
3541 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00003542 if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
Olli Etuahoac5274d2015-02-20 10:19:08 +02003543 {
Olli Etuahoac5274d2015-02-20 10:19:08 +02003544 return nullptr;
3545 }
3546 }
3547
Olli Etuahoa3a36662015-02-17 13:46:51 +02003548 TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
3549 if (node == nullptr)
3550 {
3551 error(loc, "erroneous switch statement", "switch");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003552 return nullptr;
3553 }
3554 return node;
3555}
3556
3557TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
3558{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003559 if (mSwitchNestingLevel == 0)
3560 {
3561 error(loc, "case labels need to be inside switch statements", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003562 return nullptr;
3563 }
3564 if (condition == nullptr)
3565 {
3566 error(loc, "case label must have a condition", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003567 return nullptr;
3568 }
3569 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
Jamie Madillb98c3a82015-07-23 14:26:04 -04003570 condition->isMatrix() || condition->isArray() || condition->isVector())
Olli Etuaho53f076f2015-02-20 10:55:14 +02003571 {
3572 error(condition->getLine(), "case label must be a scalar integer", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003573 }
3574 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
Olli Etuaho7c3848e2015-11-04 13:19:17 +02003575 // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
3576 // expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
3577 // fold in case labels.
3578 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
Olli Etuaho53f076f2015-02-20 10:55:14 +02003579 {
3580 error(condition->getLine(), "case label must be constant", "case");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003581 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003582 TIntermCase *node = intermediate.addCase(condition, loc);
3583 if (node == nullptr)
3584 {
3585 error(loc, "erroneous case statement", "case");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003586 return nullptr;
3587 }
3588 return node;
3589}
3590
3591TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
3592{
Olli Etuaho53f076f2015-02-20 10:55:14 +02003593 if (mSwitchNestingLevel == 0)
3594 {
3595 error(loc, "default labels need to be inside switch statements", "default");
Olli Etuaho53f076f2015-02-20 10:55:14 +02003596 return nullptr;
3597 }
Olli Etuahoa3a36662015-02-17 13:46:51 +02003598 TIntermCase *node = intermediate.addCase(nullptr, loc);
3599 if (node == nullptr)
3600 {
3601 error(loc, "erroneous default statement", "default");
Olli Etuahoa3a36662015-02-17 13:46:51 +02003602 return nullptr;
3603 }
3604 return node;
3605}
3606
Jamie Madillb98c3a82015-07-23 14:26:04 -04003607TIntermTyped *TParseContext::createUnaryMath(TOperator op,
3608 TIntermTyped *child,
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003609 const TSourceLoc &loc)
Olli Etuaho69c11b52015-03-26 12:59:00 +02003610{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003611 ASSERT(child != nullptr);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003612
3613 switch (op)
3614 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003615 case EOpLogicalNot:
3616 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
3617 child->isVector())
3618 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003619 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003620 return nullptr;
3621 }
3622 break;
3623 case EOpBitwiseNot:
3624 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
3625 child->isMatrix() || child->isArray())
3626 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003627 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003628 return nullptr;
3629 }
3630 break;
3631 case EOpPostIncrement:
3632 case EOpPreIncrement:
3633 case EOpPostDecrement:
3634 case EOpPreDecrement:
3635 case EOpNegative:
3636 case EOpPositive:
3637 if (child->getBasicType() == EbtStruct || child->getBasicType() == EbtBool ||
Martin Radev2cc85b32016-08-05 16:22:53 +03003638 child->isArray() || IsOpaqueType(child->getBasicType()))
Jamie Madillb98c3a82015-07-23 14:26:04 -04003639 {
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003640 unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003641 return nullptr;
3642 }
3643 // Operators for built-ins are already type checked against their prototype.
3644 default:
3645 break;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003646 }
3647
Olli Etuahof119a262016-08-19 15:54:22 +03003648 TIntermUnary *node = new TIntermUnary(op, child);
3649 node->setLine(loc);
Olli Etuahof119a262016-08-19 15:54:22 +03003650
Olli Etuaho77ba4082016-12-16 12:01:18 +00003651 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuahof119a262016-08-19 15:54:22 +03003652 if (foldedNode)
3653 return foldedNode;
3654
3655 return node;
Olli Etuaho69c11b52015-03-26 12:59:00 +02003656}
3657
Olli Etuaho09b22472015-02-11 11:47:26 +02003658TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
3659{
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08003660 TIntermTyped *node = createUnaryMath(op, child, loc);
Olli Etuaho69c11b52015-03-26 12:59:00 +02003661 if (node == nullptr)
Olli Etuaho09b22472015-02-11 11:47:26 +02003662 {
Olli Etuaho09b22472015-02-11 11:47:26 +02003663 return child;
3664 }
3665 return node;
3666}
3667
Jamie Madillb98c3a82015-07-23 14:26:04 -04003668TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
3669 TIntermTyped *child,
3670 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003671{
Olli Etuaho856c4972016-08-08 11:38:39 +03003672 checkCanBeLValue(loc, GetOperatorString(op), child);
Olli Etuaho09b22472015-02-11 11:47:26 +02003673 return addUnaryMath(op, child, loc);
3674}
3675
Jamie Madillb98c3a82015-07-23 14:26:04 -04003676bool TParseContext::binaryOpCommonCheck(TOperator op,
3677 TIntermTyped *left,
3678 TIntermTyped *right,
3679 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02003680{
Olli Etuaho244be012016-08-18 15:26:02 +03003681 if (left->getType().getStruct() || right->getType().getStruct())
3682 {
3683 switch (op)
3684 {
3685 case EOpIndexDirectStruct:
3686 ASSERT(left->getType().getStruct());
3687 break;
3688 case EOpEqual:
3689 case EOpNotEqual:
3690 case EOpAssign:
3691 case EOpInitialize:
3692 if (left->getType() != right->getType())
3693 {
3694 return false;
3695 }
3696 break;
3697 default:
3698 error(loc, "Invalid operation for structs", GetOperatorString(op));
3699 return false;
3700 }
3701 }
3702
Olli Etuahod6b14282015-03-17 14:31:35 +02003703 if (left->isArray() || right->isArray())
3704 {
Jamie Madill6e06b1f2015-05-14 10:01:17 -04003705 if (mShaderVersion < 300)
Olli Etuahoe79904c2015-03-18 16:56:42 +02003706 {
3707 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3708 return false;
3709 }
3710
3711 if (left->isArray() != right->isArray())
3712 {
3713 error(loc, "array / non-array mismatch", GetOperatorString(op));
3714 return false;
3715 }
3716
3717 switch (op)
3718 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003719 case EOpEqual:
3720 case EOpNotEqual:
3721 case EOpAssign:
3722 case EOpInitialize:
3723 break;
3724 default:
3725 error(loc, "Invalid operation for arrays", GetOperatorString(op));
3726 return false;
Olli Etuahoe79904c2015-03-18 16:56:42 +02003727 }
Olli Etuaho376f1b52015-04-13 13:23:41 +03003728 // At this point, size of implicitly sized arrays should be resolved.
Olli Etuahoe79904c2015-03-18 16:56:42 +02003729 if (left->getArraySize() != right->getArraySize())
3730 {
3731 error(loc, "array size mismatch", GetOperatorString(op));
3732 return false;
3733 }
Olli Etuahod6b14282015-03-17 14:31:35 +02003734 }
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003735
3736 // Check ops which require integer / ivec parameters
3737 bool isBitShift = false;
3738 switch (op)
3739 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003740 case EOpBitShiftLeft:
3741 case EOpBitShiftRight:
3742 case EOpBitShiftLeftAssign:
3743 case EOpBitShiftRightAssign:
3744 // Unsigned can be bit-shifted by signed and vice versa, but we need to
3745 // check that the basic type is an integer type.
3746 isBitShift = true;
3747 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
3748 {
3749 return false;
3750 }
3751 break;
3752 case EOpBitwiseAnd:
3753 case EOpBitwiseXor:
3754 case EOpBitwiseOr:
3755 case EOpBitwiseAndAssign:
3756 case EOpBitwiseXorAssign:
3757 case EOpBitwiseOrAssign:
3758 // It is enough to check the type of only one operand, since later it
3759 // is checked that the operand types match.
3760 if (!IsInteger(left->getBasicType()))
3761 {
3762 return false;
3763 }
3764 break;
3765 default:
3766 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003767 }
3768
3769 // GLSL ES 1.00 and 3.00 do not support implicit type casting.
3770 // So the basic type should usually match.
3771 if (!isBitShift && left->getBasicType() != right->getBasicType())
3772 {
3773 return false;
3774 }
3775
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003776 // Check that:
3777 // 1. Type sizes match exactly on ops that require that.
3778 // 2. Restrictions for structs that contain arrays or samplers are respected.
3779 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
Jamie Madillb98c3a82015-07-23 14:26:04 -04003780 switch (op)
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003781 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003782 case EOpAssign:
3783 case EOpInitialize:
3784 case EOpEqual:
3785 case EOpNotEqual:
3786 // ESSL 1.00 sections 5.7, 5.8, 5.9
3787 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
3788 {
3789 error(loc, "undefined operation for structs containing arrays",
3790 GetOperatorString(op));
3791 return false;
3792 }
3793 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
3794 // we interpret the spec so that this extends to structs containing samplers,
3795 // similarly to ESSL 1.00 spec.
3796 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
3797 left->getType().isStructureContainingSamplers())
3798 {
3799 error(loc, "undefined operation for structs containing samplers",
3800 GetOperatorString(op));
3801 return false;
3802 }
Martin Radev2cc85b32016-08-05 16:22:53 +03003803
3804 if ((op == EOpAssign || op == EOpInitialize) &&
3805 left->getType().isStructureContainingImages())
3806 {
3807 error(loc, "undefined operation for structs containing images",
3808 GetOperatorString(op));
3809 return false;
3810 }
Olli Etuahoe1805592017-01-02 16:41:20 +00003811 if ((left->getNominalSize() != right->getNominalSize()) ||
3812 (left->getSecondarySize() != right->getSecondarySize()))
3813 {
3814 error(loc, "dimension mismatch", GetOperatorString(op));
3815 return false;
3816 }
3817 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003818 case EOpLessThan:
3819 case EOpGreaterThan:
3820 case EOpLessThanEqual:
3821 case EOpGreaterThanEqual:
Olli Etuahoe1805592017-01-02 16:41:20 +00003822 if (!left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04003823 {
Olli Etuahoe1805592017-01-02 16:41:20 +00003824 error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
Jamie Madillb98c3a82015-07-23 14:26:04 -04003825 return false;
3826 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +03003827 break;
3828 case EOpAdd:
3829 case EOpSub:
3830 case EOpDiv:
3831 case EOpIMod:
3832 case EOpBitShiftLeft:
3833 case EOpBitShiftRight:
3834 case EOpBitwiseAnd:
3835 case EOpBitwiseXor:
3836 case EOpBitwiseOr:
3837 case EOpAddAssign:
3838 case EOpSubAssign:
3839 case EOpDivAssign:
3840 case EOpIModAssign:
3841 case EOpBitShiftLeftAssign:
3842 case EOpBitShiftRightAssign:
3843 case EOpBitwiseAndAssign:
3844 case EOpBitwiseXorAssign:
3845 case EOpBitwiseOrAssign:
3846 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
3847 {
3848 return false;
3849 }
3850
3851 // Are the sizes compatible?
3852 if (left->getNominalSize() != right->getNominalSize() ||
3853 left->getSecondarySize() != right->getSecondarySize())
3854 {
3855 // If the nominal sizes of operands do not match:
3856 // One of them must be a scalar.
3857 if (!left->isScalar() && !right->isScalar())
3858 return false;
3859
3860 // In the case of compound assignment other than multiply-assign,
3861 // the right side needs to be a scalar. Otherwise a vector/matrix
3862 // would be assigned to a scalar. A scalar can't be shifted by a
3863 // vector either.
3864 if (!right->isScalar() &&
3865 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
3866 return false;
3867 }
3868 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003869 default:
3870 break;
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003871 }
3872
Olli Etuahod6b14282015-03-17 14:31:35 +02003873 return true;
3874}
3875
Olli Etuaho1dded802016-08-18 18:13:13 +03003876bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
3877 const TType &left,
3878 const TType &right)
3879{
3880 switch (op)
3881 {
3882 case EOpMul:
3883 case EOpMulAssign:
3884 return left.getNominalSize() == right.getNominalSize() &&
3885 left.getSecondarySize() == right.getSecondarySize();
3886 case EOpVectorTimesScalar:
3887 return true;
3888 case EOpVectorTimesScalarAssign:
3889 ASSERT(!left.isMatrix() && !right.isMatrix());
3890 return left.isVector() && !right.isVector();
3891 case EOpVectorTimesMatrix:
3892 return left.getNominalSize() == right.getRows();
3893 case EOpVectorTimesMatrixAssign:
3894 ASSERT(!left.isMatrix() && right.isMatrix());
3895 return left.isVector() && left.getNominalSize() == right.getRows() &&
3896 left.getNominalSize() == right.getCols();
3897 case EOpMatrixTimesVector:
3898 return left.getCols() == right.getNominalSize();
3899 case EOpMatrixTimesScalar:
3900 return true;
3901 case EOpMatrixTimesScalarAssign:
3902 ASSERT(left.isMatrix() && !right.isMatrix());
3903 return !right.isVector();
3904 case EOpMatrixTimesMatrix:
3905 return left.getCols() == right.getRows();
3906 case EOpMatrixTimesMatrixAssign:
3907 ASSERT(left.isMatrix() && right.isMatrix());
3908 // We need to check two things:
3909 // 1. The matrix multiplication step is valid.
3910 // 2. The result will have the same number of columns as the lvalue.
3911 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
3912
3913 default:
3914 UNREACHABLE();
3915 return false;
3916 }
3917}
3918
Jamie Madillb98c3a82015-07-23 14:26:04 -04003919TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
3920 TIntermTyped *left,
3921 TIntermTyped *right,
3922 const TSourceLoc &loc)
Olli Etuahofc1806e2015-03-17 13:03:11 +02003923{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02003924 if (!binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02003925 return nullptr;
3926
Olli Etuahofc1806e2015-03-17 13:03:11 +02003927 switch (op)
3928 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04003929 case EOpEqual:
3930 case EOpNotEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04003931 case EOpLessThan:
3932 case EOpGreaterThan:
3933 case EOpLessThanEqual:
3934 case EOpGreaterThanEqual:
Jamie Madillb98c3a82015-07-23 14:26:04 -04003935 break;
3936 case EOpLogicalOr:
3937 case EOpLogicalXor:
3938 case EOpLogicalAnd:
Olli Etuaho244be012016-08-18 15:26:02 +03003939 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3940 !right->getType().getStruct());
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00003941 if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
Jamie Madillb98c3a82015-07-23 14:26:04 -04003942 {
3943 return nullptr;
3944 }
Olli Etuahoe7dc9d72016-11-03 16:58:47 +00003945 // Basic types matching should have been already checked.
3946 ASSERT(right->getBasicType() == EbtBool);
Jamie Madillb98c3a82015-07-23 14:26:04 -04003947 break;
3948 case EOpAdd:
3949 case EOpSub:
3950 case EOpDiv:
3951 case EOpMul:
Olli Etuaho244be012016-08-18 15:26:02 +03003952 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3953 !right->getType().getStruct());
3954 if (left->getBasicType() == EbtBool)
Jamie Madillb98c3a82015-07-23 14:26:04 -04003955 {
3956 return nullptr;
3957 }
3958 break;
3959 case EOpIMod:
Olli Etuaho244be012016-08-18 15:26:02 +03003960 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
3961 !right->getType().getStruct());
Jamie Madillb98c3a82015-07-23 14:26:04 -04003962 // Note that this is only for the % operator, not for mod()
Olli Etuaho244be012016-08-18 15:26:02 +03003963 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
Jamie Madillb98c3a82015-07-23 14:26:04 -04003964 {
3965 return nullptr;
3966 }
3967 break;
Jamie Madillb98c3a82015-07-23 14:26:04 -04003968 default:
3969 break;
Olli Etuahofc1806e2015-03-17 13:03:11 +02003970 }
3971
Olli Etuaho1dded802016-08-18 18:13:13 +03003972 if (op == EOpMul)
3973 {
3974 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
3975 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
3976 {
3977 return nullptr;
3978 }
3979 }
3980
Olli Etuaho3fdec912016-08-18 15:08:06 +03003981 TIntermBinary *node = new TIntermBinary(op, left, right);
3982 node->setLine(loc);
3983
Olli Etuaho3fdec912016-08-18 15:08:06 +03003984 // See if we can fold constants.
Olli Etuaho77ba4082016-12-16 12:01:18 +00003985 TIntermTyped *foldedNode = node->fold(mDiagnostics);
Olli Etuaho3fdec912016-08-18 15:08:06 +03003986 if (foldedNode)
3987 return foldedNode;
3988
3989 return node;
Olli Etuahofc1806e2015-03-17 13:03:11 +02003990}
3991
Jamie Madillb98c3a82015-07-23 14:26:04 -04003992TIntermTyped *TParseContext::addBinaryMath(TOperator op,
3993 TIntermTyped *left,
3994 TIntermTyped *right,
3995 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02003996{
Olli Etuahofc1806e2015-03-17 13:03:11 +02003997 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02003998 if (node == 0)
3999 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004000 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4001 right->getCompleteString());
Olli Etuaho09b22472015-02-11 11:47:26 +02004002 return left;
4003 }
4004 return node;
4005}
4006
Jamie Madillb98c3a82015-07-23 14:26:04 -04004007TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
4008 TIntermTyped *left,
4009 TIntermTyped *right,
4010 const TSourceLoc &loc)
Olli Etuaho09b22472015-02-11 11:47:26 +02004011{
Olli Etuahofc1806e2015-03-17 13:03:11 +02004012 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004013 if (node == 0)
4014 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004015 binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
4016 right->getCompleteString());
Jamie Madill6ba6ead2015-05-04 14:21:21 -04004017 TConstantUnion *unionArray = new TConstantUnion[1];
Olli Etuaho09b22472015-02-11 11:47:26 +02004018 unionArray->setBConst(false);
Jamie Madillb98c3a82015-07-23 14:26:04 -04004019 return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
4020 loc);
Olli Etuaho09b22472015-02-11 11:47:26 +02004021 }
4022 return node;
4023}
4024
Olli Etuaho13389b62016-10-16 11:48:18 +01004025TIntermBinary *TParseContext::createAssign(TOperator op,
4026 TIntermTyped *left,
4027 TIntermTyped *right,
4028 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004029{
Olli Etuaho47fd36a2015-03-19 14:22:24 +02004030 if (binaryOpCommonCheck(op, left, right, loc))
Olli Etuahod6b14282015-03-17 14:31:35 +02004031 {
Olli Etuaho1dded802016-08-18 18:13:13 +03004032 if (op == EOpMulAssign)
4033 {
4034 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
4035 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
4036 {
4037 return nullptr;
4038 }
4039 }
Olli Etuaho3fdec912016-08-18 15:08:06 +03004040 TIntermBinary *node = new TIntermBinary(op, left, right);
4041 node->setLine(loc);
4042
Olli Etuaho3fdec912016-08-18 15:08:06 +03004043 return node;
Olli Etuahod6b14282015-03-17 14:31:35 +02004044 }
4045 return nullptr;
4046}
4047
Jamie Madillb98c3a82015-07-23 14:26:04 -04004048TIntermTyped *TParseContext::addAssign(TOperator op,
4049 TIntermTyped *left,
4050 TIntermTyped *right,
4051 const TSourceLoc &loc)
Olli Etuahod6b14282015-03-17 14:31:35 +02004052{
4053 TIntermTyped *node = createAssign(op, left, right, loc);
4054 if (node == nullptr)
4055 {
4056 assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
Olli Etuahod6b14282015-03-17 14:31:35 +02004057 return left;
4058 }
4059 return node;
4060}
4061
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004062TIntermTyped *TParseContext::addComma(TIntermTyped *left,
4063 TIntermTyped *right,
4064 const TSourceLoc &loc)
4065{
Corentin Wallez0d959252016-07-12 17:26:32 -04004066 // WebGL2 section 5.26, the following results in an error:
4067 // "Sequence operator applied to void, arrays, or structs containing arrays"
Jamie Madilld7b1ab52016-12-12 14:42:19 -05004068 if (mShaderSpec == SH_WEBGL2_SPEC &&
4069 (left->isArray() || left->getBasicType() == EbtVoid ||
4070 left->getType().isStructureContainingArrays() || right->isArray() ||
4071 right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
Corentin Wallez0d959252016-07-12 17:26:32 -04004072 {
4073 error(loc,
4074 "sequence operator is not allowed for void, arrays, or structs containing arrays",
4075 ",");
Corentin Wallez0d959252016-07-12 17:26:32 -04004076 }
4077
Olli Etuaho4db7ded2016-10-13 12:23:11 +01004078 return TIntermediate::AddComma(left, right, loc, mShaderVersion);
Olli Etuaho0b2d2dc2015-11-04 16:35:32 +02004079}
4080
Olli Etuaho49300862015-02-20 14:54:49 +02004081TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
4082{
4083 switch (op)
4084 {
Jamie Madillb98c3a82015-07-23 14:26:04 -04004085 case EOpContinue:
4086 if (mLoopNestingLevel <= 0)
4087 {
4088 error(loc, "continue statement only allowed in loops", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004089 }
4090 break;
4091 case EOpBreak:
4092 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
4093 {
4094 error(loc, "break statement only allowed in loops and switch statements", "");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004095 }
4096 break;
4097 case EOpReturn:
4098 if (mCurrentFunctionType->getBasicType() != EbtVoid)
4099 {
4100 error(loc, "non-void function must return a value", "return");
Jamie Madillb98c3a82015-07-23 14:26:04 -04004101 }
4102 break;
4103 default:
4104 // No checks for discard
4105 break;
Olli Etuaho49300862015-02-20 14:54:49 +02004106 }
4107 return intermediate.addBranch(op, loc);
4108}
4109
Jamie Madillb98c3a82015-07-23 14:26:04 -04004110TIntermBranch *TParseContext::addBranch(TOperator op,
4111 TIntermTyped *returnValue,
4112 const TSourceLoc &loc)
Olli Etuaho49300862015-02-20 14:54:49 +02004113{
4114 ASSERT(op == EOpReturn);
4115 mFunctionReturnsValue = true;
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004116 if (mCurrentFunctionType->getBasicType() == EbtVoid)
Olli Etuaho49300862015-02-20 14:54:49 +02004117 {
4118 error(loc, "void function cannot return a value", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004119 }
Jamie Madill6e06b1f2015-05-14 10:01:17 -04004120 else if (*mCurrentFunctionType != returnValue->getType())
Olli Etuaho49300862015-02-20 14:54:49 +02004121 {
4122 error(loc, "function return is not matching type:", "return");
Olli Etuaho49300862015-02-20 14:54:49 +02004123 }
4124 return intermediate.addBranch(op, returnValue, loc);
4125}
4126
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004127void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
4128{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004129 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Olli Etuahobd674552016-10-06 13:28:42 +01004130 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004131 TIntermNode *offset = nullptr;
4132 TIntermSequence *arguments = functionCall->getSequence();
4133 if (name.compare(0, 16, "texelFetchOffset") == 0 ||
4134 name.compare(0, 16, "textureLodOffset") == 0 ||
4135 name.compare(0, 20, "textureProjLodOffset") == 0 ||
4136 name.compare(0, 17, "textureGradOffset") == 0 ||
4137 name.compare(0, 21, "textureProjGradOffset") == 0)
4138 {
4139 offset = arguments->back();
4140 }
4141 else if (name.compare(0, 13, "textureOffset") == 0 ||
4142 name.compare(0, 17, "textureProjOffset") == 0)
4143 {
4144 // A bias parameter might follow the offset parameter.
4145 ASSERT(arguments->size() >= 3);
4146 offset = (*arguments)[2];
4147 }
4148 if (offset != nullptr)
4149 {
4150 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
4151 if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
4152 {
4153 TString unmangledName = TFunction::unmangleName(name);
4154 error(functionCall->getLine(), "Texture offset must be a constant expression",
4155 unmangledName.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004156 }
4157 else
4158 {
4159 ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
4160 size_t size = offsetConstantUnion->getType().getObjectSize();
4161 const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
4162 for (size_t i = 0u; i < size; ++i)
4163 {
4164 int offsetValue = values[i].getIConst();
4165 if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
4166 {
4167 std::stringstream tokenStream;
4168 tokenStream << offsetValue;
4169 std::string token = tokenStream.str();
4170 error(offset->getLine(), "Texture offset value out of valid range",
4171 token.c_str());
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004172 }
4173 }
4174 }
4175 }
4176}
4177
Martin Radev2cc85b32016-08-05 16:22:53 +03004178// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
4179void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
4180{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004181 ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
Martin Radev2cc85b32016-08-05 16:22:53 +03004182 const TString &name = functionCall->getFunctionSymbolInfo()->getName();
4183
4184 if (name.compare(0, 5, "image") == 0)
4185 {
4186 TIntermSequence *arguments = functionCall->getSequence();
4187 TIntermNode *imageNode = (*arguments)[0];
4188 TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode();
4189
4190 const TMemoryQualifier &memoryQualifier = imageSymbol->getMemoryQualifier();
4191
4192 if (name.compare(5, 5, "Store") == 0)
4193 {
4194 if (memoryQualifier.readonly)
4195 {
4196 error(imageNode->getLine(),
4197 "'imageStore' cannot be used with images qualified as 'readonly'",
4198 imageSymbol->getSymbol().c_str());
4199 }
4200 }
4201 else if (name.compare(5, 4, "Load") == 0)
4202 {
4203 if (memoryQualifier.writeonly)
4204 {
4205 error(imageNode->getLine(),
4206 "'imageLoad' cannot be used with images qualified as 'writeonly'",
4207 imageSymbol->getSymbol().c_str());
4208 }
4209 }
4210 }
4211}
4212
4213// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
4214void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
4215 const TFunction *functionDefinition,
4216 const TIntermAggregate *functionCall)
4217{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004218 ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
Martin Radev2cc85b32016-08-05 16:22:53 +03004219
4220 const TIntermSequence &arguments = *functionCall->getSequence();
4221
4222 ASSERT(functionDefinition->getParamCount() == arguments.size());
4223
4224 for (size_t i = 0; i < arguments.size(); ++i)
4225 {
4226 const TType &functionArgumentType = arguments[i]->getAsTyped()->getType();
4227 const TType &functionParameterType = *functionDefinition->getParam(i).type;
4228 ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
4229
4230 if (IsImage(functionArgumentType.getBasicType()))
4231 {
4232 const TMemoryQualifier &functionArgumentMemoryQualifier =
4233 functionArgumentType.getMemoryQualifier();
4234 const TMemoryQualifier &functionParameterMemoryQualifier =
4235 functionParameterType.getMemoryQualifier();
4236 if (functionArgumentMemoryQualifier.readonly &&
4237 !functionParameterMemoryQualifier.readonly)
4238 {
4239 error(functionCall->getLine(),
4240 "Function call discards the 'readonly' qualifier from image",
4241 arguments[i]->getAsSymbolNode()->getSymbol().c_str());
4242 }
4243
4244 if (functionArgumentMemoryQualifier.writeonly &&
4245 !functionParameterMemoryQualifier.writeonly)
4246 {
4247 error(functionCall->getLine(),
4248 "Function call discards the 'writeonly' qualifier from image",
4249 arguments[i]->getAsSymbolNode()->getSymbol().c_str());
4250 }
Martin Radev049edfa2016-11-11 14:35:37 +02004251
4252 if (functionArgumentMemoryQualifier.coherent &&
4253 !functionParameterMemoryQualifier.coherent)
4254 {
4255 error(functionCall->getLine(),
4256 "Function call discards the 'coherent' qualifier from image",
4257 arguments[i]->getAsSymbolNode()->getSymbol().c_str());
4258 }
4259
4260 if (functionArgumentMemoryQualifier.volatileQualifier &&
4261 !functionParameterMemoryQualifier.volatileQualifier)
4262 {
4263 error(functionCall->getLine(),
4264 "Function call discards the 'volatile' qualifier from image",
4265 arguments[i]->getAsSymbolNode()->getSymbol().c_str());
4266 }
Martin Radev2cc85b32016-08-05 16:22:53 +03004267 }
4268 }
4269}
4270
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004271TIntermSequence *TParseContext::createEmptyArgumentsList()
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004272{
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004273 return new TIntermSequence();
Olli Etuaho72d10202017-01-19 15:58:30 +00004274}
4275
4276TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004277 TIntermSequence *arguments,
Olli Etuaho72d10202017-01-19 15:58:30 +00004278 TIntermNode *thisNode,
4279 const TSourceLoc &loc)
4280{
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004281 if (thisNode != nullptr)
4282 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004283 return addMethod(fnCall, arguments, thisNode, loc);
Olli Etuahoffe6edf2015-04-13 17:32:03 +03004284 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004285
4286 TOperator op = fnCall->getBuiltInOp();
4287 if (op != EOpNull)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004288 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004289 return addConstructor(arguments, op, fnCall->getReturnType(), loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004290 }
4291 else
4292 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004293 return addNonConstructorFunctionCall(fnCall, arguments, loc);
4294 }
4295}
4296
4297TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
4298 TIntermSequence *arguments,
4299 TIntermNode *thisNode,
4300 const TSourceLoc &loc)
4301{
4302 TConstantUnion *unionArray = new TConstantUnion[1];
4303 int arraySize = 0;
4304 TIntermTyped *typedThis = thisNode->getAsTyped();
4305 // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
4306 // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
4307 // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
4308 // So accessing fnCall->getName() below is safe.
4309 if (fnCall->getName() != "length")
4310 {
4311 error(loc, "invalid method", fnCall->getName().c_str());
4312 }
4313 else if (!arguments->empty())
4314 {
4315 error(loc, "method takes no parameters", "length");
4316 }
4317 else if (typedThis == nullptr || !typedThis->isArray())
4318 {
4319 error(loc, "length can only be called on arrays", "length");
4320 }
4321 else
4322 {
4323 arraySize = typedThis->getArraySize();
4324 if (typedThis->getAsSymbolNode() == nullptr)
Olli Etuaho72d10202017-01-19 15:58:30 +00004325 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004326 // This code path can be hit with expressions like these:
4327 // (a = b).length()
4328 // (func()).length()
4329 // (int[3](0, 1, 2)).length()
4330 // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
4331 // expression.
4332 // It allows "An array name with the length method applied" in contrast to GLSL 4.4
4333 // spec section 5.9 which allows "An array, vector or matrix expression with the
4334 // length method applied".
4335 error(loc, "length can only be called on array names, not on array expressions",
4336 "length");
Olli Etuaho72d10202017-01-19 15:58:30 +00004337 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004338 }
4339 unionArray->setIConst(arraySize);
4340 return intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
4341}
4342
4343TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
4344 TIntermSequence *arguments,
4345 const TSourceLoc &loc)
4346{
4347 // First find by unmangled name to check whether the function name has been
4348 // hidden by a variable name or struct typename.
4349 // If a function is found, check for one with a matching argument list.
4350 bool builtIn;
4351 const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn);
4352 if (symbol != nullptr && !symbol->isFunction())
4353 {
4354 error(loc, "function name expected", fnCall->getName().c_str());
4355 }
4356 else
4357 {
4358 symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments),
4359 mShaderVersion, &builtIn);
4360 if (symbol == nullptr)
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004361 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004362 error(loc, "no matching overloaded function found", fnCall->getName().c_str());
4363 }
4364 else
4365 {
4366 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004367 //
4368 // A declared function.
4369 //
Olli Etuaho383b7912016-08-05 11:22:59 +03004370 if (builtIn && !fnCandidate->getExtension().empty())
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004371 {
Olli Etuaho856c4972016-08-08 11:38:39 +03004372 checkCanUseExtension(loc, fnCandidate->getExtension());
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004373 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004374 TOperator op = fnCandidate->getBuiltInOp();
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004375 if (builtIn && op != EOpNull)
4376 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004377 // A function call mapped to a built-in operation.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004378 if (fnCandidate->getParamCount() == 1)
4379 {
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004380 // Treat it like a built-in unary operator.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004381 TIntermNode *unaryParamNode = arguments->front();
4382 TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
Olli Etuaho2be2d5a2017-01-26 16:34:30 -08004383 ASSERT(callNode != nullptr);
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004384 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004385 }
4386 else
4387 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004388 TIntermAggregate *callNode =
4389 new TIntermAggregate(fnCandidate->getReturnType(), op, arguments);
4390 callNode->setLine(loc);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004391
4392 // Some built-in functions have out parameters too.
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004393 functionCallLValueErrorCheck(fnCandidate, callNode);
Arun Patole274f0702015-05-05 13:33:30 +05304394
Olli Etuaho7c3848e2015-11-04 13:19:17 +02004395 // See if we can constant fold a built-in. Note that this may be possible even
4396 // if it is not const-qualified.
Olli Etuahof119a262016-08-19 15:54:22 +03004397 TIntermTyped *foldedNode =
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004398 intermediate.foldAggregateBuiltIn(callNode, mDiagnostics);
Arun Patole274f0702015-05-05 13:33:30 +05304399 if (foldedNode)
4400 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004401 return foldedNode;
Arun Patole274f0702015-05-05 13:33:30 +05304402 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004403 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004404 }
4405 }
4406 else
4407 {
4408 // This is a real function call
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004409 TIntermAggregate *callNode = nullptr;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004410
Olli Etuaho1ecd14b2017-01-26 13:54:15 -08004411 // If builtIn == false, the function is user defined - could be an overloaded
4412 // built-in as well.
4413 // if builtIn == true, it's a builtIn function with no op associated with it.
4414 // This needs to happen after the function info including name is set.
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004415 if (builtIn)
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004416 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004417 callNode = new TIntermAggregate(fnCandidate->getReturnType(),
4418 EOpCallBuiltInFunction, arguments);
4419 // Note that name needs to be set before texture function type is determined.
4420 callNode->getFunctionSymbolInfo()->setFromFunction(*fnCandidate);
4421 callNode->setBuiltInFunctionPrecision();
4422 checkTextureOffsetConst(callNode);
4423 checkImageMemoryAccessForBuiltinFunctions(callNode);
Martin Radev2cc85b32016-08-05 16:22:53 +03004424 }
4425 else
4426 {
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004427 callNode = new TIntermAggregate(fnCandidate->getReturnType(),
4428 EOpCallFunctionInAST, arguments);
4429 callNode->getFunctionSymbolInfo()->setFromFunction(*fnCandidate);
4430 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
Olli Etuahoe1a94c62015-11-16 17:35:25 +02004431 }
4432
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004433 functionCallLValueErrorCheck(fnCandidate, callNode);
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004434
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004435 callNode->setLine(loc);
4436
4437 return callNode;
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004438 }
4439 }
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004440 }
Olli Etuahoaf6fc1b2017-01-26 17:45:35 -08004441
4442 // Error message was already written. Put on a dummy node for error recovery.
4443 return TIntermTyped::CreateZero(TType(EbtFloat, EbpMedium, EvqConst));
Olli Etuahoc4ba3be2015-03-02 14:42:24 +02004444}
4445
Jamie Madillb98c3a82015-07-23 14:26:04 -04004446TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004447 TIntermTyped *trueExpression,
4448 TIntermTyped *falseExpression,
Olli Etuaho52901742015-04-15 13:42:45 +03004449 const TSourceLoc &loc)
4450{
Olli Etuaho856c4972016-08-08 11:38:39 +03004451 checkIsScalarBool(loc, cond);
Olli Etuaho52901742015-04-15 13:42:45 +03004452
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004453 if (trueExpression->getType() != falseExpression->getType())
Olli Etuaho52901742015-04-15 13:42:45 +03004454 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004455 binaryOpError(loc, ":", trueExpression->getCompleteString(),
4456 falseExpression->getCompleteString());
4457 return falseExpression;
Olli Etuaho52901742015-04-15 13:42:45 +03004458 }
Olli Etuahode318b22016-10-25 16:18:25 +01004459 if (IsOpaqueType(trueExpression->getBasicType()))
4460 {
4461 // ESSL 1.00 section 4.1.7
4462 // ESSL 3.00 section 4.1.7
4463 // Opaque/sampler types are not allowed in most types of expressions, including ternary.
4464 // Note that structs containing opaque types don't need to be checked as structs are
4465 // forbidden below.
4466 error(loc, "ternary operator is not allowed for opaque types", ":");
4467 return falseExpression;
4468 }
4469
Olli Etuahoa2d53032015-04-15 14:14:44 +03004470 // ESSL1 sections 5.2 and 5.7:
4471 // ESSL3 section 5.7:
4472 // Ternary operator is not among the operators allowed for structures/arrays.
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004473 if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
Olli Etuahoa2d53032015-04-15 14:14:44 +03004474 {
4475 error(loc, "ternary operator is not allowed for structures or arrays", ":");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004476 return falseExpression;
Olli Etuahoa2d53032015-04-15 14:14:44 +03004477 }
Corentin Wallez0d959252016-07-12 17:26:32 -04004478 // WebGL2 section 5.26, the following results in an error:
4479 // "Ternary operator applied to void, arrays, or structs containing arrays"
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004480 if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
Corentin Wallez0d959252016-07-12 17:26:32 -04004481 {
4482 error(loc, "ternary operator is not allowed for void", ":");
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004483 return falseExpression;
Corentin Wallez0d959252016-07-12 17:26:32 -04004484 }
4485
Olli Etuahod0bad2c2016-09-09 18:01:16 +03004486 return TIntermediate::AddTernarySelection(cond, trueExpression, falseExpression, loc);
Olli Etuaho52901742015-04-15 13:42:45 +03004487}
Olli Etuaho49300862015-02-20 14:54:49 +02004488
shannonwoods@chromium.orga9100882013-05-30 00:11:39 +00004489//
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004490// Parse an array of strings using yyparse.
4491//
4492// Returns 0 for success.
4493//
Jamie Madillb98c3a82015-07-23 14:26:04 -04004494int PaParseStrings(size_t count,
4495 const char *const string[],
4496 const int length[],
Arun Patole7e7e68d2015-05-22 12:02:25 +05304497 TParseContext *context)
4498{
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004499 if ((count == 0) || (string == NULL))
4500 return 1;
4501
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004502 if (glslang_initialize(context))
4503 return 1;
4504
alokp@chromium.org408c45e2012-04-05 15:54:43 +00004505 int error = glslang_scan(count, string, length, context);
4506 if (!error)
4507 error = glslang_parse(context);
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004508
alokp@chromium.org73bc2982012-06-19 18:48:05 +00004509 glslang_finalize(context);
alokp@chromium.org8b851c62012-06-15 16:25:11 +00004510
alokp@chromium.org6b495712012-06-29 00:06:58 +00004511 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
alokp@chromium.org044a5cf2010-11-12 15:42:16 +00004512}
Jamie Madill45bcc782016-11-07 13:58:48 -05004513
4514} // namespace sh