1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "compiler/translator/ParseContext.h"
8
9 #include <stdarg.h>
10 #include <stdio.h>
11
12 #include "common/mathutil.h"
13 #include "compiler/preprocessor/SourceLocation.h"
14 #include "compiler/translator/Declarator.h"
15 #include "compiler/translator/StaticType.h"
16 #include "compiler/translator/ValidateGlobalInitializer.h"
17 #include "compiler/translator/ValidateSwitch.h"
18 #include "compiler/translator/glslang.h"
19 #include "compiler/translator/tree_util/IntermNode_util.h"
20 #include "compiler/translator/util.h"
21
22 namespace sh
23 {
24
25 ///////////////////////////////////////////////////////////////////////
26 //
27 // Sub- vector and matrix fields
28 //
29 ////////////////////////////////////////////////////////////////////////
30
31 namespace
32 {
33
34 const int kWebGLMaxStructNesting = 4;
35
36 bool ContainsSampler(const TStructure *structType);
37
ContainsSampler(const TType & type)38 bool ContainsSampler(const TType &type)
39 {
40 if (IsSampler(type.getBasicType()))
41 {
42 return true;
43 }
44 if (type.getBasicType() == EbtStruct)
45 {
46 return ContainsSampler(type.getStruct());
47 }
48
49 return false;
50 }
51
ContainsSampler(const TStructure * structType)52 bool ContainsSampler(const TStructure *structType)
53 {
54 for (const auto &field : structType->fields())
55 {
56 if (ContainsSampler(*field->type()))
57 return true;
58 }
59 return false;
60 }
61
62 // Get a token from an image argument to use as an error message token.
GetImageArgumentToken(TIntermTyped * imageNode)63 const char *GetImageArgumentToken(TIntermTyped *imageNode)
64 {
65 ASSERT(IsImage(imageNode->getBasicType()));
66 while (imageNode->getAsBinaryNode() &&
67 (imageNode->getAsBinaryNode()->getOp() == EOpIndexIndirect ||
68 imageNode->getAsBinaryNode()->getOp() == EOpIndexDirect))
69 {
70 imageNode = imageNode->getAsBinaryNode()->getLeft();
71 }
72 TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode();
73 if (imageSymbol)
74 {
75 return imageSymbol->getName().data();
76 }
77 return "image";
78 }
79
CanSetDefaultPrecisionOnType(const TPublicType & type)80 bool CanSetDefaultPrecisionOnType(const TPublicType &type)
81 {
82 if (!SupportsPrecision(type.getBasicType()))
83 {
84 return false;
85 }
86 if (type.getBasicType() == EbtUInt)
87 {
88 // ESSL 3.00.4 section 4.5.4
89 return false;
90 }
91 if (type.isAggregate())
92 {
93 // Not allowed to set for aggregate types
94 return false;
95 }
96 return true;
97 }
98
99 // Map input primitive types to input array sizes in a geometry shader.
GetGeometryShaderInputArraySize(TLayoutPrimitiveType primitiveType)100 GLuint GetGeometryShaderInputArraySize(TLayoutPrimitiveType primitiveType)
101 {
102 switch (primitiveType)
103 {
104 case EptPoints:
105 return 1u;
106 case EptLines:
107 return 2u;
108 case EptTriangles:
109 return 3u;
110 case EptLinesAdjacency:
111 return 4u;
112 case EptTrianglesAdjacency:
113 return 6u;
114 default:
115 UNREACHABLE();
116 return 0u;
117 }
118 }
119
IsBufferOrSharedVariable(TIntermTyped * var)120 bool IsBufferOrSharedVariable(TIntermTyped *var)
121 {
122 if (var->isInterfaceBlock() || var->getQualifier() == EvqBuffer ||
123 var->getQualifier() == EvqShared)
124 {
125 return true;
126 }
127 return false;
128 }
129
FindLValueBase(TIntermTyped * node)130 TIntermTyped *FindLValueBase(TIntermTyped *node)
131 {
132 do
133 {
134 const TIntermBinary *binary = node->getAsBinaryNode();
135 if (binary == nullptr)
136 {
137 return node;
138 }
139
140 TOperator op = binary->getOp();
141 if (op != EOpIndexDirect && op != EOpIndexIndirect)
142 {
143 return static_cast<TIntermTyped *>(nullptr);
144 }
145
146 node = binary->getLeft();
147 } while (true);
148 }
149
150 } // namespace
151
152 // This tracks each binding point's current default offset for inheritance of subsequent
153 // variables using the same binding, and keeps offsets unique and non overlapping.
154 // See GLSL ES 3.1, section 4.4.6.
155 class TParseContext::AtomicCounterBindingState
156 {
157 public:
AtomicCounterBindingState()158 AtomicCounterBindingState() : mDefaultOffset(0) {}
159 // Inserts a new span and returns -1 if overlapping, else returns the starting offset of
160 // newly inserted span.
insertSpan(int start,size_t length)161 int insertSpan(int start, size_t length)
162 {
163 gl::RangeI newSpan(start, start + static_cast<int>(length));
164 for (const auto &span : mSpans)
165 {
166 if (newSpan.intersects(span))
167 {
168 return -1;
169 }
170 }
171 mSpans.push_back(newSpan);
172 mDefaultOffset = newSpan.high();
173 return start;
174 }
175 // Inserts a new span starting from the default offset.
appendSpan(size_t length)176 int appendSpan(size_t length) { return insertSpan(mDefaultOffset, length); }
setDefaultOffset(int offset)177 void setDefaultOffset(int offset) { mDefaultOffset = offset; }
178
179 private:
180 int mDefaultOffset;
181 std::vector<gl::RangeI> mSpans;
182 };
183
TParseContext(TSymbolTable & symt,TExtensionBehavior & ext,sh::GLenum type,ShShaderSpec spec,ShCompileOptions options,bool checksPrecErrors,TDiagnostics * diagnostics,const ShBuiltInResources & resources,ShShaderOutput outputType)184 TParseContext::TParseContext(TSymbolTable &symt,
185 TExtensionBehavior &ext,
186 sh::GLenum type,
187 ShShaderSpec spec,
188 ShCompileOptions options,
189 bool checksPrecErrors,
190 TDiagnostics *diagnostics,
191 const ShBuiltInResources &resources,
192 ShShaderOutput outputType)
193 : symbolTable(symt),
194 mDeferredNonEmptyDeclarationErrorCheck(false),
195 mShaderType(type),
196 mShaderSpec(spec),
197 mCompileOptions(options),
198 mShaderVersion(100),
199 mTreeRoot(nullptr),
200 mLoopNestingLevel(0),
201 mStructNestingLevel(0),
202 mSwitchNestingLevel(0),
203 mCurrentFunctionType(nullptr),
204 mFunctionReturnsValue(false),
205 mChecksPrecisionErrors(checksPrecErrors),
206 mFragmentPrecisionHighOnESSL1(false),
207 mEarlyFragmentTestsSpecified(false),
208 mDefaultUniformMatrixPacking(EmpColumnMajor),
209 mDefaultUniformBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
210 mDefaultBufferMatrixPacking(EmpColumnMajor),
211 mDefaultBufferBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
212 mDiagnostics(diagnostics),
213 mDirectiveHandler(ext,
214 *mDiagnostics,
215 mShaderVersion,
216 mShaderType,
217 resources.WEBGL_debug_shader_precision == 1),
218 mPreprocessor(mDiagnostics, &mDirectiveHandler, angle::pp::PreprocessorSettings(spec)),
219 mScanner(nullptr),
220 mMinProgramTexelOffset(resources.MinProgramTexelOffset),
221 mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
222 mMinProgramTextureGatherOffset(resources.MinProgramTextureGatherOffset),
223 mMaxProgramTextureGatherOffset(resources.MaxProgramTextureGatherOffset),
224 mComputeShaderLocalSizeDeclared(false),
225 mComputeShaderLocalSize(-1),
226 mNumViews(-1),
227 mMaxNumViews(resources.MaxViewsOVR),
228 mMaxImageUnits(resources.MaxImageUnits),
229 mMaxCombinedTextureImageUnits(resources.MaxCombinedTextureImageUnits),
230 mMaxUniformLocations(resources.MaxUniformLocations),
231 mMaxUniformBufferBindings(resources.MaxUniformBufferBindings),
232 mMaxVertexAttribs(resources.MaxVertexAttribs),
233 mMaxAtomicCounterBindings(resources.MaxAtomicCounterBindings),
234 mMaxShaderStorageBufferBindings(resources.MaxShaderStorageBufferBindings),
235 mDeclaringFunction(false),
236 mGeometryShaderInputPrimitiveType(EptUndefined),
237 mGeometryShaderOutputPrimitiveType(EptUndefined),
238 mGeometryShaderInvocations(0),
239 mGeometryShaderMaxVertices(-1),
240 mMaxGeometryShaderInvocations(resources.MaxGeometryShaderInvocations),
241 mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices),
242 mGeometryInputArraySize(0),
243 mMaxPatchVertices(resources.MaxPatchVertices),
244 mTessControlShaderOutputVertices(0),
245 mTessEvaluationShaderInputPrimitiveType(EtetUndefined),
246 mTessEvaluationShaderInputVertexSpacingType(EtetUndefined),
247 mTessEvaluationShaderInputOrderingType(EtetUndefined),
248 mTessEvaluationShaderInputPointType(EtetUndefined),
249 mFunctionBodyNewScope(false),
250 mOutputType(outputType)
251 {}
252
~TParseContext()253 TParseContext::~TParseContext() {}
254
anyMultiviewExtensionAvailable()255 bool TParseContext::anyMultiviewExtensionAvailable()
256 {
257 return isExtensionEnabled(TExtension::OVR_multiview) ||
258 isExtensionEnabled(TExtension::OVR_multiview2);
259 }
260
parseVectorFields(const TSourceLoc & line,const ImmutableString & compString,int vecSize,TVector<int> * fieldOffsets)261 bool TParseContext::parseVectorFields(const TSourceLoc &line,
262 const ImmutableString &compString,
263 int vecSize,
264 TVector<int> *fieldOffsets)
265 {
266 ASSERT(fieldOffsets);
267 size_t fieldCount = compString.length();
268 if (fieldCount > 4u)
269 {
270 error(line, "illegal vector field selection", compString);
271 return false;
272 }
273 fieldOffsets->resize(fieldCount);
274
275 enum
276 {
277 exyzw,
278 ergba,
279 estpq
280 } fieldSet[4];
281
282 for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
283 {
284 switch (compString[i])
285 {
286 case 'x':
287 (*fieldOffsets)[i] = 0;
288 fieldSet[i] = exyzw;
289 break;
290 case 'r':
291 (*fieldOffsets)[i] = 0;
292 fieldSet[i] = ergba;
293 break;
294 case 's':
295 (*fieldOffsets)[i] = 0;
296 fieldSet[i] = estpq;
297 break;
298 case 'y':
299 (*fieldOffsets)[i] = 1;
300 fieldSet[i] = exyzw;
301 break;
302 case 'g':
303 (*fieldOffsets)[i] = 1;
304 fieldSet[i] = ergba;
305 break;
306 case 't':
307 (*fieldOffsets)[i] = 1;
308 fieldSet[i] = estpq;
309 break;
310 case 'z':
311 (*fieldOffsets)[i] = 2;
312 fieldSet[i] = exyzw;
313 break;
314 case 'b':
315 (*fieldOffsets)[i] = 2;
316 fieldSet[i] = ergba;
317 break;
318 case 'p':
319 (*fieldOffsets)[i] = 2;
320 fieldSet[i] = estpq;
321 break;
322
323 case 'w':
324 (*fieldOffsets)[i] = 3;
325 fieldSet[i] = exyzw;
326 break;
327 case 'a':
328 (*fieldOffsets)[i] = 3;
329 fieldSet[i] = ergba;
330 break;
331 case 'q':
332 (*fieldOffsets)[i] = 3;
333 fieldSet[i] = estpq;
334 break;
335 default:
336 error(line, "illegal vector field selection", compString);
337 return false;
338 }
339 }
340
341 for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
342 {
343 if ((*fieldOffsets)[i] >= vecSize)
344 {
345 error(line, "vector field selection out of range", compString);
346 return false;
347 }
348
349 if (i > 0)
350 {
351 if (fieldSet[i] != fieldSet[i - 1])
352 {
353 error(line, "illegal - vector component fields not from the same set", compString);
354 return false;
355 }
356 }
357 }
358
359 return true;
360 }
361
362 ///////////////////////////////////////////////////////////////////////
363 //
364 // Errors
365 //
366 ////////////////////////////////////////////////////////////////////////
367
368 //
369 // Used by flex/bison to output all syntax and parsing errors.
370 //
error(const TSourceLoc & loc,const char * reason,const char * token)371 void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token)
372 {
373 mDiagnostics->error(loc, reason, token);
374 }
375
error(const TSourceLoc & loc,const char * reason,const ImmutableString & token)376 void TParseContext::error(const TSourceLoc &loc, const char *reason, const ImmutableString &token)
377 {
378 mDiagnostics->error(loc, reason, token.data());
379 }
380
warning(const TSourceLoc & loc,const char * reason,const char * token)381 void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token)
382 {
383 mDiagnostics->warning(loc, reason, token);
384 }
385
outOfRangeError(bool isError,const TSourceLoc & loc,const char * reason,const char * token)386 void TParseContext::outOfRangeError(bool isError,
387 const TSourceLoc &loc,
388 const char *reason,
389 const char *token)
390 {
391 if (isError)
392 {
393 error(loc, reason, token);
394 }
395 else
396 {
397 warning(loc, reason, token);
398 }
399 }
400
setTreeRoot(TIntermBlock * treeRoot)401 void TParseContext::setTreeRoot(TIntermBlock *treeRoot)
402 {
403 mTreeRoot = treeRoot;
404 mTreeRoot->setIsTreeRoot();
405 }
406
407 //
408 // Same error message for all places assignments don't work.
409 //
assignError(const TSourceLoc & line,const char * op,const TType & left,const TType & right)410 void TParseContext::assignError(const TSourceLoc &line,
411 const char *op,
412 const TType &left,
413 const TType &right)
414 {
415 TInfoSinkBase reasonStream;
416 reasonStream << "cannot convert from '" << right << "' to '" << left << "'";
417 error(line, reasonStream.c_str(), op);
418 }
419
420 //
421 // Same error message for all places unary operations don't work.
422 //
unaryOpError(const TSourceLoc & line,const char * op,const TType & operand)423 void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, const TType &operand)
424 {
425 TInfoSinkBase reasonStream;
426 reasonStream << "wrong operand type - no operation '" << op
427 << "' exists that takes an operand of type " << operand
428 << " (or there is no acceptable conversion)";
429 error(line, reasonStream.c_str(), op);
430 }
431
432 //
433 // Same error message for all binary operations don't work.
434 //
binaryOpError(const TSourceLoc & line,const char * op,const TType & left,const TType & right)435 void TParseContext::binaryOpError(const TSourceLoc &line,
436 const char *op,
437 const TType &left,
438 const TType &right)
439 {
440 TInfoSinkBase reasonStream;
441 reasonStream << "wrong operand types - no operation '" << op
442 << "' exists that takes a left-hand operand of type '" << left
443 << "' and a right operand of type '" << right
444 << "' (or there is no acceptable conversion)";
445 error(line, reasonStream.c_str(), op);
446 }
447
checkPrecisionSpecified(const TSourceLoc & line,TPrecision precision,TBasicType type)448 void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
449 TPrecision precision,
450 TBasicType type)
451 {
452 if (!mChecksPrecisionErrors)
453 return;
454
455 if (precision != EbpUndefined && !SupportsPrecision(type))
456 {
457 error(line, "illegal type for precision qualifier", getBasicString(type));
458 }
459
460 if (precision == EbpUndefined)
461 {
462 switch (type)
463 {
464 case EbtFloat:
465 error(line, "No precision specified for (float)", "");
466 return;
467 case EbtInt:
468 case EbtUInt:
469 UNREACHABLE(); // there's always a predeclared qualifier
470 error(line, "No precision specified (int)", "");
471 return;
472 default:
473 if (IsOpaqueType(type))
474 {
475 error(line, "No precision specified", getBasicString(type));
476 return;
477 }
478 }
479 }
480 }
481
markStaticReadIfSymbol(TIntermNode * node)482 void TParseContext::markStaticReadIfSymbol(TIntermNode *node)
483 {
484 TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
485 if (swizzleNode)
486 {
487 markStaticReadIfSymbol(swizzleNode->getOperand());
488 return;
489 }
490 TIntermBinary *binaryNode = node->getAsBinaryNode();
491 if (binaryNode)
492 {
493 switch (binaryNode->getOp())
494 {
495 case EOpIndexDirect:
496 case EOpIndexIndirect:
497 case EOpIndexDirectStruct:
498 case EOpIndexDirectInterfaceBlock:
499 markStaticReadIfSymbol(binaryNode->getLeft());
500 return;
501 default:
502 return;
503 }
504 }
505 TIntermSymbol *symbolNode = node->getAsSymbolNode();
506 if (symbolNode)
507 {
508 symbolTable.markStaticRead(symbolNode->variable());
509 }
510 }
511
512 // Both test and if necessary, spit out an error, to see if the node is really
513 // an l-value that can be operated on this way.
checkCanBeLValue(const TSourceLoc & line,const char * op,TIntermTyped * node)514 bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
515 {
516 TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
517 if (swizzleNode)
518 {
519 bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
520 if (ok && swizzleNode->hasDuplicateOffsets())
521 {
522 error(line, " l-value of swizzle cannot have duplicate components", op);
523 return false;
524 }
525 return ok;
526 }
527
528 TIntermBinary *binaryNode = node->getAsBinaryNode();
529 if (binaryNode)
530 {
531 switch (binaryNode->getOp())
532 {
533 case EOpIndexDirect:
534 case EOpIndexIndirect:
535 case EOpIndexDirectStruct:
536 case EOpIndexDirectInterfaceBlock:
537 if (node->getMemoryQualifier().readonly)
538 {
539 error(line, "can't modify a readonly variable", op);
540 return false;
541 }
542 return checkCanBeLValue(line, op, binaryNode->getLeft());
543 default:
544 break;
545 }
546 error(line, " l-value required", op);
547 return false;
548 }
549
550 std::string message;
551 switch (node->getQualifier())
552 {
553 case EvqConst:
554 message = "can't modify a const";
555 break;
556 case EvqConstReadOnly:
557 message = "can't modify a const";
558 break;
559 case EvqAttribute:
560 message = "can't modify an attribute";
561 break;
562 case EvqFragmentIn:
563 case EvqVertexIn:
564 case EvqGeometryIn:
565 case EvqTessControlIn:
566 case EvqTessEvaluationIn:
567 case EvqFlatIn:
568 case EvqNoPerspectiveIn:
569 case EvqSmoothIn:
570 case EvqCentroidIn:
571 case EvqSampleIn:
572 message = "can't modify an input";
573 break;
574 case EvqUniform:
575 message = "can't modify a uniform";
576 break;
577 case EvqVaryingIn:
578 message = "can't modify a varying";
579 break;
580 case EvqFragCoord:
581 message = "can't modify gl_FragCoord";
582 break;
583 case EvqFrontFacing:
584 message = "can't modify gl_FrontFacing";
585 break;
586 case EvqHelperInvocation:
587 message = "can't modify gl_HelperInvocation";
588 break;
589 case EvqPointCoord:
590 message = "can't modify gl_PointCoord";
591 break;
592 case EvqNumWorkGroups:
593 message = "can't modify gl_NumWorkGroups";
594 break;
595 case EvqWorkGroupSize:
596 message = "can't modify gl_WorkGroupSize";
597 break;
598 case EvqWorkGroupID:
599 message = "can't modify gl_WorkGroupID";
600 break;
601 case EvqLocalInvocationID:
602 message = "can't modify gl_LocalInvocationID";
603 break;
604 case EvqGlobalInvocationID:
605 message = "can't modify gl_GlobalInvocationID";
606 break;
607 case EvqLocalInvocationIndex:
608 message = "can't modify gl_LocalInvocationIndex";
609 break;
610 case EvqViewIDOVR:
611 message = "can't modify gl_ViewID_OVR";
612 break;
613 case EvqComputeIn:
614 message = "can't modify work group size variable";
615 break;
616 case EvqPerVertexIn:
617 message = "can't modify any member in gl_in";
618 break;
619 case EvqPrimitiveIDIn:
620 message = "can't modify gl_PrimitiveIDIn";
621 break;
622 case EvqInvocationID:
623 message = "can't modify gl_InvocationID";
624 break;
625 case EvqPrimitiveID:
626 if (mShaderType == GL_FRAGMENT_SHADER)
627 {
628 message = "can't modify gl_PrimitiveID in a fragment shader";
629 }
630 break;
631 case EvqLayer:
632 if (mShaderType == GL_FRAGMENT_SHADER)
633 {
634 message = "can't modify gl_Layer in a fragment shader";
635 }
636 break;
637 case EvqSampleID:
638 message = "can't modify gl_SampleID";
639 break;
640 case EvqSampleMaskIn:
641 message = "can't modify gl_SampleMaskIn";
642 break;
643 case EvqSamplePosition:
644 message = "can't modify gl_SamplePosition";
645 break;
646 case EvqClipDistance:
647 if (mShaderType == GL_FRAGMENT_SHADER)
648 {
649 message = "can't modify gl_ClipDistance in a fragment shader";
650 }
651 break;
652 case EvqCullDistance:
653 if (mShaderType == GL_FRAGMENT_SHADER)
654 {
655 message = "can't modify gl_CullDistance in a fragment shader";
656 }
657 break;
658 default:
659 //
660 // Type that can't be written to?
661 //
662 if (node->getBasicType() == EbtVoid)
663 {
664 message = "can't modify void";
665 }
666 if (IsOpaqueType(node->getBasicType()))
667 {
668 message = "can't modify a variable with type ";
669 message += getBasicString(node->getBasicType());
670 }
671 else if (node->getMemoryQualifier().readonly)
672 {
673 message = "can't modify a readonly variable";
674 }
675 }
676
677 ASSERT(binaryNode == nullptr && swizzleNode == nullptr);
678 TIntermSymbol *symNode = node->getAsSymbolNode();
679 if (message.empty() && symNode != nullptr)
680 {
681 symbolTable.markStaticWrite(symNode->variable());
682 return true;
683 }
684
685 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
686 reasonStream << "l-value required";
687 if (!message.empty())
688 {
689 if (symNode)
690 {
691 // Symbol inside an expression can't be nameless.
692 ASSERT(symNode->variable().symbolType() != SymbolType::Empty);
693 const ImmutableString &symbol = symNode->getName();
694 reasonStream << " (" << message << " \"" << symbol << "\")";
695 }
696 else
697 {
698 reasonStream << " (" << message << ")";
699 }
700 }
701 std::string reason = reasonStream.str();
702 error(line, reason.c_str(), op);
703
704 return false;
705 }
706
707 // Both test, and if necessary spit out an error, to see if the node is really
708 // a constant.
checkIsConst(TIntermTyped * node)709 void TParseContext::checkIsConst(TIntermTyped *node)
710 {
711 if (node->getQualifier() != EvqConst)
712 {
713 error(node->getLine(), "constant expression required", "");
714 }
715 }
716
717 // Both test, and if necessary spit out an error, to see if the node is really
718 // an integer.
checkIsScalarInteger(TIntermTyped * node,const char * token)719 void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
720 {
721 if (!node->isScalarInt())
722 {
723 error(node->getLine(), "integer expression required", token);
724 }
725 }
726
727 // Both test, and if necessary spit out an error, to see if we are currently
728 // globally scoped.
checkIsAtGlobalLevel(const TSourceLoc & line,const char * token)729 bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
730 {
731 if (!symbolTable.atGlobalLevel())
732 {
733 error(line, "only allowed at global scope", token);
734 return false;
735 }
736 return true;
737 }
738
739 // ESSL 3.00.5 sections 3.8 and 3.9.
740 // If it starts "gl_" or contains two consecutive underscores, it's reserved.
741 // Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a webgl shader.
checkIsNotReserved(const TSourceLoc & line,const ImmutableString & identifier)742 bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const ImmutableString &identifier)
743 {
744 static const char *reservedErrMsg = "reserved built-in name";
745 if (identifier.beginsWith("gl_"))
746 {
747 error(line, reservedErrMsg, "gl_");
748 return false;
749 }
750 if (sh::IsWebGLBasedSpec(mShaderSpec))
751 {
752 if (identifier.beginsWith("webgl_"))
753 {
754 error(line, reservedErrMsg, "webgl_");
755 return false;
756 }
757 if (identifier.beginsWith("_webgl_"))
758 {
759 error(line, reservedErrMsg, "_webgl_");
760 return false;
761 }
762 }
763 if (identifier.contains("__"))
764 {
765 error(line,
766 "identifiers containing two consecutive underscores (__) are reserved as "
767 "possible future keywords",
768 identifier);
769 return false;
770 }
771 return true;
772 }
773
774 // Make sure the argument types are correct for constructing a specific type.
checkConstructorArguments(const TSourceLoc & line,const TIntermSequence & arguments,const TType & type)775 bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
776 const TIntermSequence &arguments,
777 const TType &type)
778 {
779 if (arguments.empty())
780 {
781 error(line, "constructor does not have any arguments", "constructor");
782 return false;
783 }
784
785 for (TIntermNode *arg : arguments)
786 {
787 markStaticReadIfSymbol(arg);
788 const TIntermTyped *argTyped = arg->getAsTyped();
789 ASSERT(argTyped != nullptr);
790 if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType()))
791 {
792 std::string reason("cannot convert a variable with type ");
793 reason += getBasicString(argTyped->getBasicType());
794 error(line, reason.c_str(), "constructor");
795 return false;
796 }
797 else if (argTyped->getMemoryQualifier().writeonly)
798 {
799 error(line, "cannot convert a variable with writeonly", "constructor");
800 return false;
801 }
802 if (argTyped->getBasicType() == EbtVoid)
803 {
804 error(line, "cannot convert a void", "constructor");
805 return false;
806 }
807 }
808
809 if (type.isArray())
810 {
811 // The size of an unsized constructor should already have been determined.
812 ASSERT(!type.isUnsizedArray());
813 if (static_cast<size_t>(type.getOutermostArraySize()) != arguments.size())
814 {
815 error(line, "array constructor needs one argument per array element", "constructor");
816 return false;
817 }
818 // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
819 // the array.
820 for (TIntermNode *const &argNode : arguments)
821 {
822 const TType &argType = argNode->getAsTyped()->getType();
823 if (mShaderVersion < 310 && argType.isArray())
824 {
825 error(line, "constructing from a non-dereferenced array", "constructor");
826 return false;
827 }
828 if (!argType.isElementTypeOf(type))
829 {
830 error(line, "Array constructor argument has an incorrect type", "constructor");
831 return false;
832 }
833 }
834 }
835 else if (type.getBasicType() == EbtStruct)
836 {
837 const TFieldList &fields = type.getStruct()->fields();
838 if (fields.size() != arguments.size())
839 {
840 error(line,
841 "Number of constructor parameters does not match the number of structure fields",
842 "constructor");
843 return false;
844 }
845
846 for (size_t i = 0; i < fields.size(); i++)
847 {
848 if (i >= arguments.size() ||
849 arguments[i]->getAsTyped()->getType() != *fields[i]->type())
850 {
851 error(line, "Structure constructor arguments do not match structure fields",
852 "constructor");
853 return false;
854 }
855 }
856 }
857 else
858 {
859 // We're constructing a scalar, vector, or matrix.
860
861 // Note: It's okay to have too many components available, but not okay to have unused
862 // arguments. 'full' will go to true when enough args have been seen. If we loop again,
863 // there is an extra argument, so 'overFull' will become true.
864
865 size_t size = 0;
866 bool full = false;
867 bool overFull = false;
868 bool matrixArg = false;
869 for (TIntermNode *arg : arguments)
870 {
871 const TIntermTyped *argTyped = arg->getAsTyped();
872 ASSERT(argTyped != nullptr);
873
874 if (argTyped->getBasicType() == EbtStruct)
875 {
876 error(line, "a struct cannot be used as a constructor argument for this type",
877 "constructor");
878 return false;
879 }
880 if (argTyped->getType().isArray())
881 {
882 error(line, "constructing from a non-dereferenced array", "constructor");
883 return false;
884 }
885 if (argTyped->getType().isMatrix())
886 {
887 matrixArg = true;
888 }
889
890 size += argTyped->getType().getObjectSize();
891 if (full)
892 {
893 overFull = true;
894 }
895 if (size >= type.getObjectSize())
896 {
897 full = true;
898 }
899 }
900
901 if (type.isMatrix() && matrixArg)
902 {
903 if (arguments.size() != 1)
904 {
905 error(line, "constructing matrix from matrix can only take one argument",
906 "constructor");
907 return false;
908 }
909 }
910 else
911 {
912 if (size != 1 && size < type.getObjectSize())
913 {
914 error(line, "not enough data provided for construction", "constructor");
915 return false;
916 }
917 if (overFull)
918 {
919 error(line, "too many arguments", "constructor");
920 return false;
921 }
922 }
923 }
924
925 return true;
926 }
927
928 // This function checks to see if a void variable has been declared and raise an error message for
929 // such a case
930 //
931 // returns true in case of an error
932 //
checkIsNonVoid(const TSourceLoc & line,const ImmutableString & identifier,const TBasicType & type)933 bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
934 const ImmutableString &identifier,
935 const TBasicType &type)
936 {
937 if (type == EbtVoid)
938 {
939 error(line, "illegal use of type 'void'", identifier);
940 return false;
941 }
942
943 return true;
944 }
945
946 // This function checks to see if the node (for the expression) contains a scalar boolean expression
947 // or not.
checkIsScalarBool(const TSourceLoc & line,const TIntermTyped * type)948 bool TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
949 {
950 if (type->getBasicType() != EbtBool || !type->isScalar())
951 {
952 error(line, "boolean expression expected", "");
953 return false;
954 }
955 return true;
956 }
957
958 // This function checks to see if the node (for the expression) contains a scalar boolean expression
959 // or not.
checkIsScalarBool(const TSourceLoc & line,const TPublicType & pType)960 void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
961 {
962 if (pType.getBasicType() != EbtBool || pType.isAggregate())
963 {
964 error(line, "boolean expression expected", "");
965 }
966 }
967
checkIsNotOpaqueType(const TSourceLoc & line,const TTypeSpecifierNonArray & pType,const char * reason)968 bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
969 const TTypeSpecifierNonArray &pType,
970 const char *reason)
971 {
972 if (pType.type == EbtStruct)
973 {
974 if (ContainsSampler(pType.userDef))
975 {
976 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
977 reasonStream << reason << " (structure contains a sampler)";
978 std::string reasonStr = reasonStream.str();
979 error(line, reasonStr.c_str(), getBasicString(pType.type));
980 return false;
981 }
982 // only samplers need to be checked from structs, since other opaque types can't be struct
983 // members.
984 return true;
985 }
986 else if (IsOpaqueType(pType.type))
987 {
988 error(line, reason, getBasicString(pType.type));
989 return false;
990 }
991
992 return true;
993 }
994
checkDeclaratorLocationIsNotSpecified(const TSourceLoc & line,const TPublicType & pType)995 void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
996 const TPublicType &pType)
997 {
998 if (pType.layoutQualifier.location != -1)
999 {
1000 error(line, "location must only be specified for a single input or output variable",
1001 "location");
1002 }
1003 }
1004
checkLocationIsNotSpecified(const TSourceLoc & location,const TLayoutQualifier & layoutQualifier)1005 void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
1006 const TLayoutQualifier &layoutQualifier)
1007 {
1008 if (layoutQualifier.location != -1)
1009 {
1010 const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs";
1011 if (mShaderVersion >= 310)
1012 {
1013 errorMsg =
1014 "invalid layout qualifier: only valid on shader inputs, outputs, and uniforms";
1015 }
1016 error(location, errorMsg, "location");
1017 }
1018 }
1019
checkStd430IsForShaderStorageBlock(const TSourceLoc & location,const TLayoutBlockStorage & blockStorage,const TQualifier & qualifier)1020 void TParseContext::checkStd430IsForShaderStorageBlock(const TSourceLoc &location,
1021 const TLayoutBlockStorage &blockStorage,
1022 const TQualifier &qualifier)
1023 {
1024 if (blockStorage == EbsStd430 && qualifier != EvqBuffer)
1025 {
1026 error(location, "The std430 layout is supported only for shader storage blocks.", "std430");
1027 }
1028 }
1029
checkOutParameterIsNotOpaqueType(const TSourceLoc & line,TQualifier qualifier,const TType & type)1030 void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
1031 TQualifier qualifier,
1032 const TType &type)
1033 {
1034 ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
1035 if (IsOpaqueType(type.getBasicType()))
1036 {
1037 error(line, "opaque types cannot be output parameters", type.getBasicString());
1038 }
1039 }
1040
1041 // Do size checking for an array type's size.
checkIsValidArraySize(const TSourceLoc & line,TIntermTyped * expr)1042 unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
1043 {
1044 TIntermConstantUnion *constant = expr->getAsConstantUnion();
1045
1046 // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be
1047 // safe against corner cases we still check for constant folding. Some interpretations of the
1048 // spec have allowed constant expressions with side effects - like array length() method on a
1049 // non-constant array.
1050 if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
1051 {
1052 error(line, "array size must be a constant integer expression", "");
1053 return 1u;
1054 }
1055
1056 unsigned int size = 0u;
1057
1058 if (constant->getBasicType() == EbtUInt)
1059 {
1060 size = constant->getUConst(0);
1061 }
1062 else
1063 {
1064 int signedSize = constant->getIConst(0);
1065
1066 if (signedSize < 0)
1067 {
1068 error(line, "array size must be non-negative", "");
1069 return 1u;
1070 }
1071
1072 size = static_cast<unsigned int>(signedSize);
1073 }
1074
1075 if (size == 0u)
1076 {
1077 error(line, "array size must be greater than zero", "");
1078 return 1u;
1079 }
1080
1081 if (IsOutputHLSL(getOutputType()))
1082 {
1083 // The size of arrays is restricted here to prevent issues further down the
1084 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
1085 // 4096 registers so this should be reasonable even for aggressively optimizable code.
1086 const unsigned int sizeLimit = 65536;
1087
1088 if (size > sizeLimit)
1089 {
1090 error(line, "array size too large", "");
1091 return 1u;
1092 }
1093 }
1094
1095 return size;
1096 }
1097
1098 // See if this qualifier can be an array.
checkIsValidQualifierForArray(const TSourceLoc & line,const TPublicType & elementQualifier)1099 bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
1100 const TPublicType &elementQualifier)
1101 {
1102 if ((elementQualifier.qualifier == EvqAttribute) ||
1103 (elementQualifier.qualifier == EvqVertexIn) ||
1104 (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
1105 {
1106 error(line, "cannot declare arrays of this qualifier",
1107 TType(elementQualifier).getQualifierString());
1108 return false;
1109 }
1110
1111 return true;
1112 }
1113
1114 // See if this element type can be formed into an array.
checkArrayElementIsNotArray(const TSourceLoc & line,const TPublicType & elementType)1115 bool TParseContext::checkArrayElementIsNotArray(const TSourceLoc &line,
1116 const TPublicType &elementType)
1117 {
1118 if (mShaderVersion < 310 && elementType.isArray())
1119 {
1120 TInfoSinkBase typeString;
1121 typeString << TType(elementType);
1122 error(line, "cannot declare arrays of arrays", typeString.c_str());
1123 return false;
1124 }
1125 return true;
1126 }
1127
1128 // Check for array-of-arrays being used as non-allowed shader inputs/outputs.
checkArrayOfArraysInOut(const TSourceLoc & line,const TPublicType & elementType,const TType & arrayType)1129 bool TParseContext::checkArrayOfArraysInOut(const TSourceLoc &line,
1130 const TPublicType &elementType,
1131 const TType &arrayType)
1132 {
1133 if (arrayType.isArrayOfArrays())
1134 {
1135 if (elementType.qualifier == EvqVertexOut)
1136 {
1137 error(line, "vertex shader output cannot be an array of arrays",
1138 TType(elementType).getQualifierString());
1139 return false;
1140 }
1141 if (elementType.qualifier == EvqFragmentIn)
1142 {
1143 error(line, "fragment shader input cannot be an array of arrays",
1144 TType(elementType).getQualifierString());
1145 return false;
1146 }
1147 if (elementType.qualifier == EvqFragmentOut || elementType.qualifier == EvqFragmentInOut)
1148 {
1149 error(line, "fragment shader output cannot be an array of arrays",
1150 TType(elementType).getQualifierString());
1151 return false;
1152 }
1153 }
1154 return true;
1155 }
1156
1157 // Check if this qualified element type can be formed into an array. This is only called when array
1158 // brackets are associated with an identifier in a declaration, like this:
1159 // float a[2];
1160 // Similar checks are done in addFullySpecifiedType for array declarations where the array brackets
1161 // are associated with the type, like this:
1162 // float[2] a;
checkIsValidTypeAndQualifierForArray(const TSourceLoc & indexLocation,const TPublicType & elementType)1163 bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
1164 const TPublicType &elementType)
1165 {
1166 if (!checkArrayElementIsNotArray(indexLocation, elementType))
1167 {
1168 return false;
1169 }
1170 // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
1171 // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
1172 // 4.3.4).
1173 // Geometry shader requires each user-defined input be declared as arrays or inside input
1174 // blocks declared as arrays (GL_EXT_geometry_shader section 11.1gs.4.3). For the purposes of
1175 // interface matching, such variables and blocks are treated as though they were not declared
1176 // as arrays (GL_EXT_geometry_shader section 7.4.1).
1177 if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
1178 sh::IsVarying(elementType.qualifier) &&
1179 !IsGeometryShaderInput(mShaderType, elementType.qualifier) &&
1180 !IsTessellationControlShaderInput(mShaderType, elementType.qualifier) &&
1181 !IsTessellationEvaluationShaderInput(mShaderType, elementType.qualifier) &&
1182 !IsTessellationControlShaderOutput(mShaderType, elementType.qualifier))
1183 {
1184 TInfoSinkBase typeString;
1185 typeString << TType(elementType);
1186 error(indexLocation, "cannot declare arrays of structs of this qualifier",
1187 typeString.c_str());
1188 return false;
1189 }
1190 return checkIsValidQualifierForArray(indexLocation, elementType);
1191 }
1192
1193 // Enforce non-initializer type/qualifier rules.
checkCanBeDeclaredWithoutInitializer(const TSourceLoc & line,const ImmutableString & identifier,TType * type)1194 void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
1195 const ImmutableString &identifier,
1196 TType *type)
1197 {
1198 ASSERT(type != nullptr);
1199 if (type->getQualifier() == EvqConst)
1200 {
1201 // Make the qualifier make sense.
1202 type->setQualifier(EvqTemporary);
1203
1204 // Generate informative error messages for ESSL1.
1205 // In ESSL3 arrays and structures containing arrays can be constant.
1206 if (mShaderVersion < 300 && type->isStructureContainingArrays())
1207 {
1208 error(line,
1209 "structures containing arrays may not be declared constant since they cannot be "
1210 "initialized",
1211 identifier);
1212 }
1213 else
1214 {
1215 error(line, "variables with qualifier 'const' must be initialized", identifier);
1216 }
1217 }
1218
1219 // Implicitly declared arrays are disallowed for shaders other than tessellation shaders.
1220 if (mShaderType != GL_TESS_CONTROL_SHADER && mShaderType != GL_TESS_EVALUATION_SHADER &&
1221 type->isArray())
1222 {
1223 const TSpan<const unsigned int> &arraySizes = type->getArraySizes();
1224 for (unsigned int size : arraySizes)
1225 {
1226 if (size == 0)
1227 {
1228 error(line,
1229 "implicitly sized arrays disallowed for shaders that are not tessellation "
1230 "shaders",
1231 identifier);
1232 }
1233 }
1234 }
1235 }
1236
1237 // Do some simple checks that are shared between all variable declarations,
1238 // and update the symbol table.
1239 //
1240 // Returns true if declaring the variable succeeded.
1241 //
declareVariable(const TSourceLoc & line,const ImmutableString & identifier,const TType * type,TVariable ** variable)1242 bool TParseContext::declareVariable(const TSourceLoc &line,
1243 const ImmutableString &identifier,
1244 const TType *type,
1245 TVariable **variable)
1246 {
1247 ASSERT((*variable) == nullptr);
1248
1249 (*variable) = new TVariable(&symbolTable, identifier, type, SymbolType::UserDefined);
1250
1251 ASSERT(type->getLayoutQualifier().index == -1 ||
1252 (isExtensionEnabled(TExtension::EXT_blend_func_extended) &&
1253 mShaderType == GL_FRAGMENT_SHADER && mShaderVersion >= 300));
1254 if (type->getQualifier() == EvqFragmentOut)
1255 {
1256 if (type->getLayoutQualifier().index != -1 && type->getLayoutQualifier().location == -1)
1257 {
1258 error(line,
1259 "If index layout qualifier is specified for a fragment output, location must "
1260 "also be specified.",
1261 "index");
1262 return false;
1263 }
1264 }
1265 else
1266 {
1267 checkIndexIsNotSpecified(line, type->getLayoutQualifier().index);
1268 }
1269
1270 if (!((identifier.beginsWith("gl_LastFragData") || type->getQualifier() == EvqFragmentInOut) &&
1271 (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) ||
1272 isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent))))
1273 {
1274 checkNoncoherentIsNotSpecified(line, type->getLayoutQualifier().noncoherent);
1275 }
1276 else if (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent) &&
1277 !isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch))
1278 {
1279 checkNoncoherentIsSpecified(line, type->getLayoutQualifier().noncoherent);
1280 }
1281
1282 checkBindingIsValid(line, *type);
1283
1284 bool needsReservedCheck = true;
1285
1286 // gl_LastFragData may be redeclared with a new precision qualifier
1287 if (type->isArray() && identifier.beginsWith("gl_LastFragData"))
1288 {
1289 const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
1290 symbolTable.findBuiltIn(ImmutableString("gl_MaxDrawBuffers"), mShaderVersion));
1291 if (type->isArrayOfArrays())
1292 {
1293 error(line, "redeclaration of gl_LastFragData as an array of arrays", identifier);
1294 return false;
1295 }
1296 else if (static_cast<int>(type->getOutermostArraySize()) ==
1297 maxDrawBuffers->getConstPointer()->getIConst())
1298 {
1299 if (const TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
1300 {
1301 needsReservedCheck = !checkCanUseOneOfExtensions(line, builtInSymbol->extensions());
1302 }
1303 }
1304 else
1305 {
1306 error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
1307 identifier);
1308 return false;
1309 }
1310 }
1311 else if (type->isArray() && identifier == "gl_ClipDistance")
1312 {
1313 // gl_ClipDistance can be redeclared with smaller size than gl_MaxClipDistances
1314 const TVariable *maxClipDistances = static_cast<const TVariable *>(
1315 symbolTable.findBuiltIn(ImmutableString("gl_MaxClipDistances"), mShaderVersion));
1316 if (!maxClipDistances)
1317 {
1318 // Unsupported extension
1319 needsReservedCheck = true;
1320 }
1321 else if (type->isArrayOfArrays())
1322 {
1323 error(line, "redeclaration of gl_ClipDistance as an array of arrays", identifier);
1324 return false;
1325 }
1326 else if (static_cast<int>(type->getOutermostArraySize()) <=
1327 maxClipDistances->getConstPointer()->getIConst())
1328 {
1329 if (const TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
1330 {
1331 needsReservedCheck = !checkCanUseOneOfExtensions(line, builtInSymbol->extensions());
1332 }
1333 }
1334 else
1335 {
1336 error(line, "redeclaration of gl_ClipDistance with size > gl_MaxClipDistances",
1337 identifier);
1338 return false;
1339 }
1340 }
1341 else if (type->isArray() && identifier == "gl_CullDistance")
1342 {
1343 // gl_CullDistance can be redeclared with smaller size than gl_MaxCullDistances
1344 const TVariable *maxCullDistances = static_cast<const TVariable *>(
1345 symbolTable.findBuiltIn(ImmutableString("gl_MaxCullDistances"), mShaderVersion));
1346 if (!maxCullDistances)
1347 {
1348 // Unsupported extension
1349 needsReservedCheck = true;
1350 }
1351 else if (type->isArrayOfArrays())
1352 {
1353 error(line, "redeclaration of gl_CullDistance as an array of arrays", identifier);
1354 return false;
1355 }
1356 else if (static_cast<int>(type->getOutermostArraySize()) <=
1357 maxCullDistances->getConstPointer()->getIConst())
1358 {
1359 if (const TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
1360 {
1361 needsReservedCheck = !checkCanUseOneOfExtensions(line, builtInSymbol->extensions());
1362 }
1363 }
1364 else
1365 {
1366 error(line, "redeclaration of gl_CullDistance with size > gl_MaxCullDistances",
1367 identifier);
1368 return false;
1369 }
1370 }
1371
1372 if (needsReservedCheck && !checkIsNotReserved(line, identifier))
1373 return false;
1374
1375 if (!symbolTable.declare(*variable))
1376 {
1377 error(line, "redefinition", identifier);
1378 return false;
1379 }
1380
1381 if (!checkIsNonVoid(line, identifier, type->getBasicType()))
1382 return false;
1383
1384 return true;
1385 }
1386
checkIsParameterQualifierValid(const TSourceLoc & line,const TTypeQualifierBuilder & typeQualifierBuilder,TType * type)1387 void TParseContext::checkIsParameterQualifierValid(
1388 const TSourceLoc &line,
1389 const TTypeQualifierBuilder &typeQualifierBuilder,
1390 TType *type)
1391 {
1392 // The only parameter qualifiers a parameter can have are in, out, inout or const.
1393 TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics);
1394
1395 if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
1396 {
1397 checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type);
1398 }
1399
1400 if (!IsImage(type->getBasicType()))
1401 {
1402 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line);
1403 }
1404 else
1405 {
1406 type->setMemoryQualifier(typeQualifier.memoryQualifier);
1407 }
1408
1409 type->setQualifier(typeQualifier.qualifier);
1410
1411 if (typeQualifier.precision != EbpUndefined)
1412 {
1413 type->setPrecision(typeQualifier.precision);
1414 }
1415 }
1416
1417 template <size_t size>
checkCanUseOneOfExtensions(const TSourceLoc & line,const std::array<TExtension,size> & extensions)1418 bool TParseContext::checkCanUseOneOfExtensions(const TSourceLoc &line,
1419 const std::array<TExtension, size> &extensions)
1420 {
1421 ASSERT(!extensions.empty());
1422 const TExtensionBehavior &extBehavior = extensionBehavior();
1423
1424 bool canUseWithWarning = false;
1425 bool canUseWithoutWarning = false;
1426
1427 const char *errorMsgString = "";
1428 TExtension errorMsgExtension = TExtension::UNDEFINED;
1429
1430 for (TExtension extension : extensions)
1431 {
1432 auto extIter = extBehavior.find(extension);
1433 if (canUseWithWarning)
1434 {
1435 // We already have an extension that we can use, but with a warning.
1436 // See if we can use the alternative extension without a warning.
1437 if (extIter == extBehavior.end())
1438 {
1439 continue;
1440 }
1441 if (extIter->second == EBhEnable || extIter->second == EBhRequire)
1442 {
1443 canUseWithoutWarning = true;
1444 break;
1445 }
1446 continue;
1447 }
1448 if (extension == TExtension::UNDEFINED)
1449 {
1450 continue;
1451 }
1452 else if (extIter == extBehavior.end())
1453 {
1454 errorMsgString = "extension is not supported";
1455 errorMsgExtension = extension;
1456 }
1457 else if (extIter->second == EBhUndefined || extIter->second == EBhDisable)
1458 {
1459 errorMsgString = "extension is disabled";
1460 errorMsgExtension = extension;
1461 }
1462 else if (extIter->second == EBhWarn)
1463 {
1464 errorMsgExtension = extension;
1465 canUseWithWarning = true;
1466 }
1467 else
1468 {
1469 ASSERT(extIter->second == EBhEnable || extIter->second == EBhRequire);
1470 canUseWithoutWarning = true;
1471 break;
1472 }
1473 }
1474
1475 if (canUseWithoutWarning)
1476 {
1477 return true;
1478 }
1479 if (canUseWithWarning)
1480 {
1481 warning(line, "extension is being used", GetExtensionNameString(errorMsgExtension));
1482 return true;
1483 }
1484 error(line, errorMsgString, GetExtensionNameString(errorMsgExtension));
1485 return false;
1486 }
1487
1488 template bool TParseContext::checkCanUseOneOfExtensions(
1489 const TSourceLoc &line,
1490 const std::array<TExtension, 1> &extensions);
1491 template bool TParseContext::checkCanUseOneOfExtensions(
1492 const TSourceLoc &line,
1493 const std::array<TExtension, 2> &extensions);
1494 template bool TParseContext::checkCanUseOneOfExtensions(
1495 const TSourceLoc &line,
1496 const std::array<TExtension, 3> &extensions);
1497
checkCanUseExtension(const TSourceLoc & line,TExtension extension)1498 bool TParseContext::checkCanUseExtension(const TSourceLoc &line, TExtension extension)
1499 {
1500 ASSERT(extension != TExtension::UNDEFINED);
1501 return checkCanUseOneOfExtensions(line, std::array<TExtension, 1u>{{extension}});
1502 }
1503
1504 // ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause
1505 // compile-time or link-time errors are the same whether or not the declaration is empty".
1506 // This function implements all the checks that are done on qualifiers regardless of if the
1507 // declaration is empty.
declarationQualifierErrorCheck(const sh::TQualifier qualifier,const sh::TLayoutQualifier & layoutQualifier,const TSourceLoc & location)1508 void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier,
1509 const sh::TLayoutQualifier &layoutQualifier,
1510 const TSourceLoc &location)
1511 {
1512 if (qualifier == EvqShared && !layoutQualifier.isEmpty())
1513 {
1514 error(location, "Shared memory declarations cannot have layout specified", "layout");
1515 }
1516
1517 if (layoutQualifier.matrixPacking != EmpUnspecified)
1518 {
1519 error(location, "layout qualifier only valid for interface blocks",
1520 getMatrixPackingString(layoutQualifier.matrixPacking));
1521 return;
1522 }
1523
1524 if (layoutQualifier.blockStorage != EbsUnspecified)
1525 {
1526 error(location, "layout qualifier only valid for interface blocks",
1527 getBlockStorageString(layoutQualifier.blockStorage));
1528 return;
1529 }
1530
1531 if (qualifier == EvqFragmentOut)
1532 {
1533 if (layoutQualifier.location != -1 && layoutQualifier.yuv == true)
1534 {
1535 error(location, "invalid layout qualifier combination", "yuv");
1536 return;
1537 }
1538 }
1539 else
1540 {
1541 checkYuvIsNotSpecified(location, layoutQualifier.yuv);
1542 }
1543
1544 if (qualifier != EvqFragmentIn)
1545 {
1546 checkEarlyFragmentTestsIsNotSpecified(location, layoutQualifier.earlyFragmentTests);
1547 }
1548
1549 // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous
1550 // parsing steps. So it needs to be checked here.
1551 if (anyMultiviewExtensionAvailable() && mShaderVersion < 300 && qualifier == EvqVertexIn)
1552 {
1553 error(location, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
1554 }
1555
1556 bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut;
1557 if (mShaderVersion >= 300 &&
1558 (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) ||
1559 isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent)))
1560 {
1561 // In the case of EXT_shader_framebuffer_fetch or EXT_shader_framebuffer_fetch_non_coherent
1562 // extension, the location of inout qualifier is used to set the input attachment index
1563 canHaveLocation = canHaveLocation || qualifier == EvqFragmentInOut;
1564 }
1565 if (mShaderVersion >= 310)
1566 {
1567 canHaveLocation = canHaveLocation || qualifier == EvqUniform || IsVarying(qualifier);
1568 // We're not checking whether the uniform location is in range here since that depends on
1569 // the type of the variable.
1570 // The type can only be fully determined for non-empty declarations.
1571 }
1572 if (!canHaveLocation)
1573 {
1574 checkLocationIsNotSpecified(location, layoutQualifier);
1575 }
1576 }
1577
atomicCounterQualifierErrorCheck(const TPublicType & publicType,const TSourceLoc & location)1578 void TParseContext::atomicCounterQualifierErrorCheck(const TPublicType &publicType,
1579 const TSourceLoc &location)
1580 {
1581 if (publicType.precision != EbpHigh)
1582 {
1583 error(location, "Can only be highp", "atomic counter");
1584 }
1585 // dEQP enforces compile error if location is specified. See uniform_location.test.
1586 if (publicType.layoutQualifier.location != -1)
1587 {
1588 error(location, "location must not be set for atomic_uint", "layout");
1589 }
1590 if (publicType.layoutQualifier.binding == -1)
1591 {
1592 error(location, "no binding specified", "atomic counter");
1593 }
1594 }
1595
emptyDeclarationErrorCheck(const TType & type,const TSourceLoc & location)1596 void TParseContext::emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location)
1597 {
1598 if (type.isUnsizedArray())
1599 {
1600 // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1601 // error. It is assumed that this applies to empty declarations as well.
1602 error(location, "empty array declaration needs to specify a size", "");
1603 }
1604
1605 if (type.getQualifier() != EvqFragmentOut)
1606 {
1607 checkIndexIsNotSpecified(location, type.getLayoutQualifier().index);
1608 }
1609 }
1610
1611 // These checks are done for all declarations that are non-empty. They're done for non-empty
1612 // declarations starting a declarator list, and declarators that follow an empty declaration.
nonEmptyDeclarationErrorCheck(const TPublicType & publicType,const TSourceLoc & identifierLocation)1613 void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
1614 const TSourceLoc &identifierLocation)
1615 {
1616 switch (publicType.qualifier)
1617 {
1618 case EvqVaryingIn:
1619 case EvqVaryingOut:
1620 case EvqAttribute:
1621 case EvqVertexIn:
1622 case EvqFragmentOut:
1623 case EvqFragmentInOut:
1624 case EvqComputeIn:
1625 if (publicType.getBasicType() == EbtStruct)
1626 {
1627 error(identifierLocation, "cannot be used with a structure",
1628 getQualifierString(publicType.qualifier));
1629 return;
1630 }
1631 break;
1632 case EvqBuffer:
1633 if (publicType.getBasicType() != EbtInterfaceBlock)
1634 {
1635 error(identifierLocation,
1636 "cannot declare buffer variables at global scope(outside a block)",
1637 getQualifierString(publicType.qualifier));
1638 return;
1639 }
1640 break;
1641 default:
1642 break;
1643 }
1644 std::string reason(getBasicString(publicType.getBasicType()));
1645 reason += "s must be uniform";
1646 if (publicType.qualifier != EvqUniform &&
1647 !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str()))
1648 {
1649 return;
1650 }
1651
1652 if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal &&
1653 publicType.qualifier != EvqConst) &&
1654 publicType.getBasicType() == EbtYuvCscStandardEXT)
1655 {
1656 error(identifierLocation, "cannot be used with a yuvCscStandardEXT",
1657 getQualifierString(publicType.qualifier));
1658 return;
1659 }
1660
1661 if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform)
1662 {
1663 // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized.
1664 // But invalid shaders may still reach here with an unsized array declaration.
1665 TType type(publicType);
1666 if (!type.isUnsizedArray())
1667 {
1668 checkUniformLocationInRange(identifierLocation, type.getLocationCount(),
1669 publicType.layoutQualifier);
1670 }
1671 }
1672
1673 if (mShaderVersion >= 300 && publicType.qualifier == EvqVertexIn)
1674 {
1675 // Valid vertex input declarations can't be unsized arrays since they can't be initialized.
1676 // But invalid shaders may still reach here with an unsized array declaration.
1677 TType type(publicType);
1678 if (!type.isUnsizedArray())
1679 {
1680 checkAttributeLocationInRange(identifierLocation, type.getLocationCount(),
1681 publicType.layoutQualifier);
1682 }
1683 }
1684
1685 // check for layout qualifier issues
1686 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
1687
1688 if (IsImage(publicType.getBasicType()))
1689 {
1690
1691 switch (layoutQualifier.imageInternalFormat)
1692 {
1693 case EiifRGBA32F:
1694 case EiifRGBA16F:
1695 case EiifR32F:
1696 case EiifRGBA8:
1697 case EiifRGBA8_SNORM:
1698 if (!IsFloatImage(publicType.getBasicType()))
1699 {
1700 error(identifierLocation,
1701 "internal image format requires a floating image type",
1702 getBasicString(publicType.getBasicType()));
1703 return;
1704 }
1705 break;
1706 case EiifRGBA32I:
1707 case EiifRGBA16I:
1708 case EiifRGBA8I:
1709 case EiifR32I:
1710 if (!IsIntegerImage(publicType.getBasicType()))
1711 {
1712 error(identifierLocation,
1713 "internal image format requires an integer image type",
1714 getBasicString(publicType.getBasicType()));
1715 return;
1716 }
1717 break;
1718 case EiifRGBA32UI:
1719 case EiifRGBA16UI:
1720 case EiifRGBA8UI:
1721 case EiifR32UI:
1722 if (!IsUnsignedImage(publicType.getBasicType()))
1723 {
1724 error(identifierLocation,
1725 "internal image format requires an unsigned image type",
1726 getBasicString(publicType.getBasicType()));
1727 return;
1728 }
1729 break;
1730 case EiifUnspecified:
1731 error(identifierLocation, "layout qualifier", "No image internal format specified");
1732 return;
1733 default:
1734 error(identifierLocation, "layout qualifier", "unrecognized token");
1735 return;
1736 }
1737
1738 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
1739 switch (layoutQualifier.imageInternalFormat)
1740 {
1741 case EiifR32F:
1742 case EiifR32I:
1743 case EiifR32UI:
1744 break;
1745 default:
1746 if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
1747 {
1748 error(identifierLocation, "layout qualifier",
1749 "Except for images with the r32f, r32i and r32ui format qualifiers, "
1750 "image variables must be qualified readonly and/or writeonly");
1751 return;
1752 }
1753 break;
1754 }
1755 }
1756 else
1757 {
1758 checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat);
1759 checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
1760 }
1761
1762 if (IsAtomicCounter(publicType.getBasicType()))
1763 {
1764 atomicCounterQualifierErrorCheck(publicType, identifierLocation);
1765 }
1766 else
1767 {
1768 checkOffsetIsNotSpecified(identifierLocation, layoutQualifier.offset);
1769 }
1770 }
1771
checkBindingIsValid(const TSourceLoc & identifierLocation,const TType & type)1772 void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type)
1773 {
1774 TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
1775 // Note that the ESSL 3.10 section 4.4.5 is not particularly clear on how the binding qualifier
1776 // on arrays of arrays should be handled. We interpret the spec so that the binding value is
1777 // incremented for each element of the innermost nested arrays. This is in line with how arrays
1778 // of arrays of blocks are specified to behave in GLSL 4.50 and a conservative interpretation
1779 // when it comes to which shaders are accepted by the compiler.
1780 int arrayTotalElementCount = type.getArraySizeProduct();
1781 if (IsImage(type.getBasicType()))
1782 {
1783 checkImageBindingIsValid(identifierLocation, layoutQualifier.binding,
1784 arrayTotalElementCount);
1785 }
1786 else if (IsSampler(type.getBasicType()))
1787 {
1788 checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding,
1789 arrayTotalElementCount);
1790 }
1791 else if (IsAtomicCounter(type.getBasicType()))
1792 {
1793 checkAtomicCounterBindingIsValid(identifierLocation, layoutQualifier.binding);
1794 }
1795 else
1796 {
1797 ASSERT(!IsOpaqueType(type.getBasicType()));
1798 checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
1799 }
1800 }
1801
checkCanUseLayoutQualifier(const TSourceLoc & location)1802 void TParseContext::checkCanUseLayoutQualifier(const TSourceLoc &location)
1803 {
1804 constexpr std::array<TExtension, 2u> extensions{
1805 {TExtension::EXT_shader_framebuffer_fetch,
1806 TExtension::EXT_shader_framebuffer_fetch_non_coherent}};
1807 if (getShaderVersion() < 300 && !checkCanUseOneOfExtensions(location, extensions))
1808 {
1809 error(location, "qualifier supported in GLSL ES 3.00 and above only", "layout");
1810 }
1811 }
1812
checkLayoutQualifierSupported(const TSourceLoc & location,const ImmutableString & layoutQualifierName,int versionRequired)1813 bool TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
1814 const ImmutableString &layoutQualifierName,
1815 int versionRequired)
1816 {
1817
1818 if (mShaderVersion < versionRequired)
1819 {
1820 error(location, "invalid layout qualifier: not supported", layoutQualifierName);
1821 return false;
1822 }
1823 return true;
1824 }
1825
checkWorkGroupSizeIsNotSpecified(const TSourceLoc & location,const TLayoutQualifier & layoutQualifier)1826 bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
1827 const TLayoutQualifier &layoutQualifier)
1828 {
1829 const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
1830 for (size_t i = 0u; i < localSize.size(); ++i)
1831 {
1832 if (localSize[i] != -1)
1833 {
1834 error(location,
1835 "invalid layout qualifier: only valid when used with 'in' in a compute shader "
1836 "global layout declaration",
1837 getWorkGroupSizeString(i));
1838 return false;
1839 }
1840 }
1841
1842 return true;
1843 }
1844
checkInternalFormatIsNotSpecified(const TSourceLoc & location,TLayoutImageInternalFormat internalFormat)1845 void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
1846 TLayoutImageInternalFormat internalFormat)
1847 {
1848 if (internalFormat != EiifUnspecified)
1849 {
1850 error(location, "invalid layout qualifier: only valid when used with images",
1851 getImageInternalFormatString(internalFormat));
1852 }
1853 }
1854
checkIndexIsNotSpecified(const TSourceLoc & location,int index)1855 void TParseContext::checkIndexIsNotSpecified(const TSourceLoc &location, int index)
1856 {
1857 if (index != -1)
1858 {
1859 error(location,
1860 "invalid layout qualifier: only valid when used with a fragment shader output in "
1861 "ESSL version >= 3.00 and EXT_blend_func_extended is enabled",
1862 "index");
1863 }
1864 }
1865
checkBindingIsNotSpecified(const TSourceLoc & location,int binding)1866 void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
1867 {
1868 if (binding != -1)
1869 {
1870 error(location,
1871 "invalid layout qualifier: only valid when used with opaque types or blocks",
1872 "binding");
1873 }
1874 }
1875
checkOffsetIsNotSpecified(const TSourceLoc & location,int offset)1876 void TParseContext::checkOffsetIsNotSpecified(const TSourceLoc &location, int offset)
1877 {
1878 if (offset != -1)
1879 {
1880 error(location, "invalid layout qualifier: only valid when used with atomic counters",
1881 "offset");
1882 }
1883 }
1884
checkImageBindingIsValid(const TSourceLoc & location,int binding,int arrayTotalElementCount)1885 void TParseContext::checkImageBindingIsValid(const TSourceLoc &location,
1886 int binding,
1887 int arrayTotalElementCount)
1888 {
1889 // Expects arraySize to be 1 when setting binding for only a single variable.
1890 if (binding >= 0 && binding + arrayTotalElementCount > mMaxImageUnits)
1891 {
1892 error(location, "image binding greater than gl_MaxImageUnits", "binding");
1893 }
1894 }
1895
checkSamplerBindingIsValid(const TSourceLoc & location,int binding,int arrayTotalElementCount)1896 void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location,
1897 int binding,
1898 int arrayTotalElementCount)
1899 {
1900 // Expects arraySize to be 1 when setting binding for only a single variable.
1901 if (binding >= 0 && binding + arrayTotalElementCount > mMaxCombinedTextureImageUnits)
1902 {
1903 error(location, "sampler binding greater than maximum texture units", "binding");
1904 }
1905 }
1906
checkBlockBindingIsValid(const TSourceLoc & location,const TQualifier & qualifier,int binding,int arraySize)1907 void TParseContext::checkBlockBindingIsValid(const TSourceLoc &location,
1908 const TQualifier &qualifier,
1909 int binding,
1910 int arraySize)
1911 {
1912 int size = (arraySize == 0 ? 1 : arraySize);
1913 if (qualifier == EvqUniform)
1914 {
1915 if (binding + size > mMaxUniformBufferBindings)
1916 {
1917 error(location, "uniform block binding greater than MAX_UNIFORM_BUFFER_BINDINGS",
1918 "binding");
1919 }
1920 }
1921 else if (qualifier == EvqBuffer)
1922 {
1923 if (binding + size > mMaxShaderStorageBufferBindings)
1924 {
1925 error(location,
1926 "shader storage block binding greater than MAX_SHADER_STORAGE_BUFFER_BINDINGS",
1927 "binding");
1928 }
1929 }
1930 }
checkAtomicCounterBindingIsValid(const TSourceLoc & location,int binding)1931 void TParseContext::checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding)
1932 {
1933 if (binding >= mMaxAtomicCounterBindings)
1934 {
1935 error(location, "atomic counter binding greater than gl_MaxAtomicCounterBindings",
1936 "binding");
1937 }
1938 }
1939
checkUniformLocationInRange(const TSourceLoc & location,int objectLocationCount,const TLayoutQualifier & layoutQualifier)1940 void TParseContext::checkUniformLocationInRange(const TSourceLoc &location,
1941 int objectLocationCount,
1942 const TLayoutQualifier &layoutQualifier)
1943 {
1944 int loc = layoutQualifier.location;
1945 if (loc >= 0) // Shader-specified location
1946 {
1947 if (loc >= mMaxUniformLocations || objectLocationCount > mMaxUniformLocations ||
1948 static_cast<unsigned int>(loc) + static_cast<unsigned int>(objectLocationCount) >
1949 static_cast<unsigned int>(mMaxUniformLocations))
1950 {
1951 error(location, "Uniform location out of range", "location");
1952 }
1953 }
1954 }
1955
checkAttributeLocationInRange(const TSourceLoc & location,int objectLocationCount,const TLayoutQualifier & layoutQualifier)1956 void TParseContext::checkAttributeLocationInRange(const TSourceLoc &location,
1957 int objectLocationCount,
1958 const TLayoutQualifier &layoutQualifier)
1959 {
1960 int loc = layoutQualifier.location;
1961 if (loc >= 0) // Shader-specified location
1962 {
1963 if (loc >= mMaxVertexAttribs || objectLocationCount > mMaxVertexAttribs ||
1964 static_cast<unsigned int>(loc) + static_cast<unsigned int>(objectLocationCount) >
1965 static_cast<unsigned int>(mMaxVertexAttribs))
1966 {
1967 error(location, "Attribute location out of range", "location");
1968 }
1969 }
1970 }
1971
checkYuvIsNotSpecified(const TSourceLoc & location,bool yuv)1972 void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv)
1973 {
1974 if (yuv != false)
1975 {
1976 error(location, "invalid layout qualifier: only valid on program outputs", "yuv");
1977 }
1978 }
1979
checkEarlyFragmentTestsIsNotSpecified(const TSourceLoc & location,bool earlyFragmentTests)1980 void TParseContext::checkEarlyFragmentTestsIsNotSpecified(const TSourceLoc &location,
1981 bool earlyFragmentTests)
1982 {
1983 if (earlyFragmentTests != false)
1984 {
1985 error(location,
1986 "invalid layout qualifier: only valid when used with 'in' in a fragment shader",
1987 "early_fragment_tests");
1988 }
1989 }
1990
checkNoncoherentIsSpecified(const TSourceLoc & location,bool noncoherent)1991 void TParseContext::checkNoncoherentIsSpecified(const TSourceLoc &location, bool noncoherent)
1992 {
1993 if (noncoherent == false)
1994 {
1995 error(location,
1996 "'noncoherent' qualifier must be used when "
1997 "GL_EXT_shader_framebuffer_fetch_non_coherent extension is used",
1998 "noncoherent");
1999 }
2000 }
2001
checkNoncoherentIsNotSpecified(const TSourceLoc & location,bool noncoherent)2002 void TParseContext::checkNoncoherentIsNotSpecified(const TSourceLoc &location, bool noncoherent)
2003 {
2004 if (noncoherent != false)
2005 {
2006 error(location,
2007 "invalid layout qualifier: only valid when used with 'gl_LastFragData' or the "
2008 "variable decorated with 'inout' in a fragment shader",
2009 "noncoherent");
2010 }
2011 }
2012
checkTCSOutVarIndexIsValid(TIntermBinary * binaryExpression,const TSourceLoc & location)2013 void TParseContext::checkTCSOutVarIndexIsValid(TIntermBinary *binaryExpression,
2014 const TSourceLoc &location)
2015 {
2016 ASSERT(binaryExpression->getOp() == EOpIndexIndirect ||
2017 binaryExpression->getOp() == EOpIndexDirect);
2018 const TIntermSymbol *intermSymbol = binaryExpression->getRight()->getAsSymbolNode();
2019 if ((intermSymbol == nullptr) || (intermSymbol->getName() != "gl_InvocationID"))
2020 {
2021 error(location,
2022 "tessellation-control per-vertex output l-value must be indexed with "
2023 "gl_InvocationID",
2024 "[");
2025 }
2026 }
2027
functionCallRValueLValueErrorCheck(const TFunction * fnCandidate,TIntermAggregate * fnCall)2028 void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandidate,
2029 TIntermAggregate *fnCall)
2030 {
2031 for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
2032 {
2033 TQualifier qual = fnCandidate->getParam(i)->getType().getQualifier();
2034 TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
2035 bool argumentIsRead = (IsQualifierUnspecified(qual) || qual == EvqIn || qual == EvqInOut ||
2036 qual == EvqConstReadOnly);
2037 if (argumentIsRead)
2038 {
2039 markStaticReadIfSymbol(argument);
2040 if (!IsImage(argument->getBasicType()))
2041 {
2042 if (argument->getMemoryQualifier().writeonly)
2043 {
2044 error(argument->getLine(),
2045 "Writeonly value cannot be passed for 'in' or 'inout' parameters.",
2046 fnCall->functionName());
2047 return;
2048 }
2049 }
2050 }
2051 if (qual == EvqOut || qual == EvqInOut)
2052 {
2053 if (!checkCanBeLValue(argument->getLine(), "assign", argument))
2054 {
2055 error(argument->getLine(),
2056 "Constant value cannot be passed for 'out' or 'inout' parameters.",
2057 fnCall->functionName());
2058 return;
2059 }
2060 }
2061 }
2062 }
2063
checkInvariantVariableQualifier(bool invariant,const TQualifier qualifier,const TSourceLoc & invariantLocation)2064 void TParseContext::checkInvariantVariableQualifier(bool invariant,
2065 const TQualifier qualifier,
2066 const TSourceLoc &invariantLocation)
2067 {
2068 if (!invariant)
2069 return;
2070
2071 if (mShaderVersion < 300)
2072 {
2073 // input variables in the fragment shader can be also qualified as invariant
2074 if (!sh::CanBeInvariantESSL1(qualifier))
2075 {
2076 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
2077 }
2078 }
2079 else
2080 {
2081 if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
2082 {
2083 error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
2084 }
2085 }
2086 }
2087
isExtensionEnabled(TExtension extension) const2088 bool TParseContext::isExtensionEnabled(TExtension extension) const
2089 {
2090 return IsExtensionEnabled(extensionBehavior(), extension);
2091 }
2092
handleExtensionDirective(const TSourceLoc & loc,const char * extName,const char * behavior)2093 void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
2094 const char *extName,
2095 const char *behavior)
2096 {
2097 angle::pp::SourceLocation srcLoc;
2098 srcLoc.file = loc.first_file;
2099 srcLoc.line = loc.first_line;
2100 mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
2101 }
2102
handlePragmaDirective(const TSourceLoc & loc,const char * name,const char * value,bool stdgl)2103 void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
2104 const char *name,
2105 const char *value,
2106 bool stdgl)
2107 {
2108 angle::pp::SourceLocation srcLoc;
2109 srcLoc.file = loc.first_file;
2110 srcLoc.line = loc.first_line;
2111 mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
2112 }
2113
getComputeShaderLocalSize() const2114 sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
2115 {
2116 sh::WorkGroupSize result(-1);
2117 for (size_t i = 0u; i < result.size(); ++i)
2118 {
2119 if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
2120 {
2121 result[i] = 1;
2122 }
2123 else
2124 {
2125 result[i] = mComputeShaderLocalSize[i];
2126 }
2127 }
2128 return result;
2129 }
2130
addScalarLiteral(const TConstantUnion * constantUnion,const TSourceLoc & line)2131 TIntermConstantUnion *TParseContext::addScalarLiteral(const TConstantUnion *constantUnion,
2132 const TSourceLoc &line)
2133 {
2134 TIntermConstantUnion *node = new TIntermConstantUnion(
2135 constantUnion, TType(constantUnion->getType(), EbpUndefined, EvqConst));
2136 node->setLine(line);
2137 return node;
2138 }
2139
2140 /////////////////////////////////////////////////////////////////////////////////
2141 //
2142 // Non-Errors.
2143 //
2144 /////////////////////////////////////////////////////////////////////////////////
2145
getNamedVariable(const TSourceLoc & location,const ImmutableString & name,const TSymbol * symbol)2146 const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
2147 const ImmutableString &name,
2148 const TSymbol *symbol)
2149 {
2150 if (!symbol)
2151 {
2152 error(location, "undeclared identifier", name);
2153 return nullptr;
2154 }
2155
2156 if (!symbol->isVariable())
2157 {
2158 error(location, "variable expected", name);
2159 return nullptr;
2160 }
2161
2162 const TVariable *variable = static_cast<const TVariable *>(symbol);
2163
2164 if (!variable->extensions().empty() && variable->extensions()[0] != TExtension::UNDEFINED)
2165 {
2166 checkCanUseOneOfExtensions(location, variable->extensions());
2167 }
2168
2169 // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
2170 if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
2171 variable->getType().getQualifier() == EvqWorkGroupSize)
2172 {
2173 error(location,
2174 "It is an error to use gl_WorkGroupSize before declaring the local group size",
2175 "gl_WorkGroupSize");
2176 }
2177
2178 // If EXT_shader_framebuffer_fetch_non_coherent is used, gl_LastFragData should be decorated
2179 // with 'layout(noncoherent)' EXT_shader_framebuffer_fetch_non_coherent spec: "Unless the
2180 // GL_EXT_shader_framebuffer_fetch extension has been enabled in addition, it's an error to use
2181 // gl_LastFragData if it hasn't been explicitly redeclared with layout(noncoherent)."
2182 if (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent) &&
2183 !isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) &&
2184 variable->getType().getQualifier() == EvqLastFragData)
2185 {
2186 checkNoncoherentIsSpecified(location, variable->getType().getLayoutQualifier().noncoherent);
2187 }
2188 return variable;
2189 }
2190
parseVariableIdentifier(const TSourceLoc & location,const ImmutableString & name,const TSymbol * symbol)2191 TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
2192 const ImmutableString &name,
2193 const TSymbol *symbol)
2194 {
2195 const TVariable *variable = getNamedVariable(location, name, symbol);
2196
2197 if (!variable)
2198 {
2199 TIntermTyped *node = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
2200 node->setLine(location);
2201 return node;
2202 }
2203
2204 const TType &variableType = variable->getType();
2205 TIntermTyped *node = nullptr;
2206
2207 if (variable->getConstPointer() && variableType.canReplaceWithConstantUnion())
2208 {
2209 const TConstantUnion *constArray = variable->getConstPointer();
2210 node = new TIntermConstantUnion(constArray, variableType);
2211 }
2212 else if (variableType.getQualifier() == EvqWorkGroupSize && mComputeShaderLocalSizeDeclared)
2213 {
2214 // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
2215 // needs to be added to the AST as a constant and not as a symbol.
2216 sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
2217 TConstantUnion *constArray = new TConstantUnion[3];
2218 for (size_t i = 0; i < 3; ++i)
2219 {
2220 constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
2221 }
2222
2223 ASSERT(variableType.getBasicType() == EbtUInt);
2224 ASSERT(variableType.getObjectSize() == 3);
2225
2226 TType type(variableType);
2227 type.setQualifier(EvqConst);
2228 node = new TIntermConstantUnion(constArray, type);
2229 }
2230 else if ((mGeometryShaderInputPrimitiveType != EptUndefined) &&
2231 (variableType.getQualifier() == EvqPerVertexIn))
2232 {
2233 ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr);
2234 node = new TIntermSymbol(symbolTable.getGlInVariableWithArraySize());
2235 }
2236 else
2237 {
2238 node = new TIntermSymbol(variable);
2239 }
2240 ASSERT(node != nullptr);
2241 node->setLine(location);
2242 return node;
2243 }
2244
2245 // Initializers show up in several places in the grammar. Have one set of
2246 // code to handle them here.
2247 //
2248 // Returns true on success.
executeInitializer(const TSourceLoc & line,const ImmutableString & identifier,TType * type,TIntermTyped * initializer,TIntermBinary ** initNode)2249 bool TParseContext::executeInitializer(const TSourceLoc &line,
2250 const ImmutableString &identifier,
2251 TType *type,
2252 TIntermTyped *initializer,
2253 TIntermBinary **initNode)
2254 {
2255 ASSERT(initNode != nullptr);
2256 ASSERT(*initNode == nullptr);
2257
2258 if (type->isUnsizedArray())
2259 {
2260 // In case initializer is not an array or type has more dimensions than initializer, this
2261 // will default to setting array sizes to 1. We have not checked yet whether the initializer
2262 // actually is an array or not. Having a non-array initializer for an unsized array will
2263 // result in an error later, so we don't generate an error message here.
2264 type->sizeUnsizedArrays(initializer->getType().getArraySizes());
2265 }
2266
2267 const TQualifier qualifier = type->getQualifier();
2268
2269 bool constError = false;
2270 if (qualifier == EvqConst)
2271 {
2272 if (EvqConst != initializer->getType().getQualifier())
2273 {
2274 TInfoSinkBase reasonStream;
2275 reasonStream << "assigning non-constant to '" << *type << "'";
2276 error(line, reasonStream.c_str(), "=");
2277
2278 // We're still going to declare the variable to avoid extra error messages.
2279 type->setQualifier(EvqTemporary);
2280 constError = true;
2281 }
2282 }
2283
2284 TVariable *variable = nullptr;
2285 if (!declareVariable(line, identifier, type, &variable))
2286 {
2287 return false;
2288 }
2289
2290 if (constError)
2291 {
2292 return false;
2293 }
2294
2295 bool nonConstGlobalInitializers =
2296 IsExtensionEnabled(mDirectiveHandler.extensionBehavior(),
2297 TExtension::EXT_shader_non_constant_global_initializers);
2298 bool globalInitWarning = false;
2299 if (symbolTable.atGlobalLevel() &&
2300 !ValidateGlobalInitializer(initializer, mShaderVersion, sh::IsWebGLBasedSpec(mShaderSpec),
2301 nonConstGlobalInitializers, &globalInitWarning))
2302 {
2303 // Error message does not completely match behavior with ESSL 1.00, but
2304 // we want to steer developers towards only using constant expressions.
2305 error(line, "global variable initializers must be constant expressions", "=");
2306 return false;
2307 }
2308 if (globalInitWarning)
2309 {
2310 warning(
2311 line,
2312 "global variable initializers should be constant expressions "
2313 "(uniforms and globals are allowed in global initializers for legacy compatibility)",
2314 "=");
2315 }
2316
2317 // identifier must be of type constant, a global, or a temporary
2318 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
2319 {
2320 error(line, " cannot initialize this type of qualifier ",
2321 variable->getType().getQualifierString());
2322 return false;
2323 }
2324
2325 TIntermSymbol *intermSymbol = new TIntermSymbol(variable);
2326 intermSymbol->setLine(line);
2327
2328 if (!binaryOpCommonCheck(EOpInitialize, intermSymbol, initializer, line))
2329 {
2330 assignError(line, "=", variable->getType(), initializer->getType());
2331 return false;
2332 }
2333
2334 if (qualifier == EvqConst)
2335 {
2336 // Save the constant folded value to the variable if possible.
2337 const TConstantUnion *constArray = initializer->getConstantValue();
2338 if (constArray)
2339 {
2340 variable->shareConstPointer(constArray);
2341 if (initializer->getType().canReplaceWithConstantUnion())
2342 {
2343 ASSERT(*initNode == nullptr);
2344 return true;
2345 }
2346 }
2347 }
2348
2349 *initNode = new TIntermBinary(EOpInitialize, intermSymbol, initializer);
2350 markStaticReadIfSymbol(initializer);
2351 (*initNode)->setLine(line);
2352 return true;
2353 }
2354
addConditionInitializer(const TPublicType & pType,const ImmutableString & identifier,TIntermTyped * initializer,const TSourceLoc & loc)2355 TIntermNode *TParseContext::addConditionInitializer(const TPublicType &pType,
2356 const ImmutableString &identifier,
2357 TIntermTyped *initializer,
2358 const TSourceLoc &loc)
2359 {
2360 checkIsScalarBool(loc, pType);
2361 TIntermBinary *initNode = nullptr;
2362 TType *type = new TType(pType);
2363 if (executeInitializer(loc, identifier, type, initializer, &initNode))
2364 {
2365 // The initializer is valid. The init condition needs to have a node - either the
2366 // initializer node, or a constant node in case the initialized variable is const and won't
2367 // be recorded in the AST.
2368 if (initNode == nullptr)
2369 {
2370 return initializer;
2371 }
2372 else
2373 {
2374 TIntermDeclaration *declaration = new TIntermDeclaration();
2375 declaration->appendDeclarator(initNode);
2376 return declaration;
2377 }
2378 }
2379 return nullptr;
2380 }
2381
addLoop(TLoopType type,TIntermNode * init,TIntermNode * cond,TIntermTyped * expr,TIntermNode * body,const TSourceLoc & line)2382 TIntermNode *TParseContext::addLoop(TLoopType type,
2383 TIntermNode *init,
2384 TIntermNode *cond,
2385 TIntermTyped *expr,
2386 TIntermNode *body,
2387 const TSourceLoc &line)
2388 {
2389 TIntermNode *node = nullptr;
2390 TIntermTyped *typedCond = nullptr;
2391 if (cond)
2392 {
2393 markStaticReadIfSymbol(cond);
2394 typedCond = cond->getAsTyped();
2395 }
2396 if (expr)
2397 {
2398 markStaticReadIfSymbol(expr);
2399 }
2400 // In case the loop body was not parsed as a block and contains a statement that simply refers
2401 // to a variable, we need to mark it as statically used.
2402 if (body)
2403 {
2404 markStaticReadIfSymbol(body);
2405 }
2406 if (cond == nullptr || typedCond)
2407 {
2408 if (type == ELoopDoWhile)
2409 {
2410 checkIsScalarBool(line, typedCond);
2411 }
2412 // In the case of other loops, it was checked before that the condition is a scalar boolean.
2413 ASSERT(mDiagnostics->numErrors() > 0 || typedCond == nullptr ||
2414 (typedCond->getBasicType() == EbtBool && !typedCond->isArray() &&
2415 !typedCond->isVector()));
2416
2417 node = new TIntermLoop(type, init, typedCond, expr, EnsureBlock(body));
2418 node->setLine(line);
2419 return node;
2420 }
2421
2422 ASSERT(type != ELoopDoWhile);
2423
2424 TIntermDeclaration *declaration = cond->getAsDeclarationNode();
2425 ASSERT(declaration);
2426 TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode();
2427 ASSERT(declarator->getLeft()->getAsSymbolNode());
2428
2429 // The condition is a declaration. In the AST representation we don't support declarations as
2430 // loop conditions. Wrap the loop to a block that declares the condition variable and contains
2431 // the loop.
2432 TIntermBlock *block = new TIntermBlock();
2433
2434 TIntermDeclaration *declareCondition = new TIntermDeclaration();
2435 declareCondition->appendDeclarator(declarator->getLeft()->deepCopy());
2436 block->appendStatement(declareCondition);
2437
2438 TIntermBinary *conditionInit = new TIntermBinary(EOpAssign, declarator->getLeft()->deepCopy(),
2439 declarator->getRight()->deepCopy());
2440 TIntermLoop *loop = new TIntermLoop(type, init, conditionInit, expr, EnsureBlock(body));
2441 block->appendStatement(loop);
2442 loop->setLine(line);
2443 block->setLine(line);
2444 return block;
2445 }
2446
addIfElse(TIntermTyped * cond,TIntermNodePair code,const TSourceLoc & loc)2447 TIntermNode *TParseContext::addIfElse(TIntermTyped *cond,
2448 TIntermNodePair code,
2449 const TSourceLoc &loc)
2450 {
2451 bool isScalarBool = checkIsScalarBool(loc, cond);
2452 // In case the conditional statements were not parsed as blocks and contain a statement that
2453 // simply refers to a variable, we need to mark them as statically used.
2454 if (code.node1)
2455 {
2456 markStaticReadIfSymbol(code.node1);
2457 }
2458 if (code.node2)
2459 {
2460 markStaticReadIfSymbol(code.node2);
2461 }
2462
2463 // For compile time constant conditions, prune the code now.
2464 if (isScalarBool && cond->getAsConstantUnion())
2465 {
2466 if (cond->getAsConstantUnion()->getBConst(0) == true)
2467 {
2468 return EnsureBlock(code.node1);
2469 }
2470 else
2471 {
2472 return EnsureBlock(code.node2);
2473 }
2474 }
2475
2476 TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2));
2477 markStaticReadIfSymbol(cond);
2478 node->setLine(loc);
2479
2480 return node;
2481 }
2482
addFullySpecifiedType(TPublicType * typeSpecifier)2483 void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
2484 {
2485 checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
2486 typeSpecifier->getBasicType());
2487
2488 if (mShaderVersion < 300 && typeSpecifier->isArray())
2489 {
2490 error(typeSpecifier->getLine(), "not supported", "first-class array");
2491 typeSpecifier->clearArrayness();
2492 }
2493 }
2494
addFullySpecifiedType(const TTypeQualifierBuilder & typeQualifierBuilder,const TPublicType & typeSpecifier)2495 TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
2496 const TPublicType &typeSpecifier)
2497 {
2498 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
2499
2500 TPublicType returnType = typeSpecifier;
2501 returnType.qualifier = typeQualifier.qualifier;
2502 returnType.invariant = typeQualifier.invariant;
2503 returnType.precise = typeQualifier.precise;
2504 returnType.layoutQualifier = typeQualifier.layoutQualifier;
2505 returnType.memoryQualifier = typeQualifier.memoryQualifier;
2506 returnType.precision = typeSpecifier.precision;
2507
2508 if (typeQualifier.precision != EbpUndefined)
2509 {
2510 returnType.precision = typeQualifier.precision;
2511 }
2512
2513 checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
2514 typeSpecifier.getBasicType());
2515
2516 checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
2517 typeSpecifier.getLine());
2518
2519 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
2520
2521 checkEarlyFragmentTestsIsNotSpecified(typeSpecifier.getLine(),
2522 returnType.layoutQualifier.earlyFragmentTests);
2523
2524 if (mShaderVersion < 300)
2525 {
2526 if (typeSpecifier.isArray())
2527 {
2528 error(typeSpecifier.getLine(), "not supported", "first-class array");
2529 returnType.clearArrayness();
2530 }
2531
2532 if (returnType.qualifier == EvqAttribute &&
2533 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
2534 {
2535 error(typeSpecifier.getLine(), "cannot be bool or int",
2536 getQualifierString(returnType.qualifier));
2537 }
2538
2539 if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
2540 (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
2541 {
2542 error(typeSpecifier.getLine(), "cannot be bool or int",
2543 getQualifierString(returnType.qualifier));
2544 }
2545 }
2546 else
2547 {
2548 if (!returnType.layoutQualifier.isEmpty())
2549 {
2550 checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
2551 }
2552 if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
2553 returnType.qualifier == EvqFragmentOut || returnType.qualifier == EvqFragmentInOut)
2554 {
2555 checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
2556 typeSpecifier.getLine());
2557 }
2558 if (returnType.qualifier == EvqComputeIn)
2559 {
2560 error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
2561 "in");
2562 }
2563 }
2564
2565 return returnType;
2566 }
2567
checkInputOutputTypeIsValidES3(const TQualifier qualifier,const TPublicType & type,const TSourceLoc & qualifierLocation)2568 void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
2569 const TPublicType &type,
2570 const TSourceLoc &qualifierLocation)
2571 {
2572 // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
2573 if (type.getBasicType() == EbtBool)
2574 {
2575 error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
2576 }
2577
2578 // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
2579 switch (qualifier)
2580 {
2581 case EvqVertexIn:
2582 // ESSL 3.00 section 4.3.4
2583 if (type.isArray())
2584 {
2585 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
2586 }
2587 // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
2588 return;
2589 case EvqFragmentOut:
2590 case EvqFragmentInOut:
2591 // ESSL 3.00 section 4.3.6
2592 if (type.typeSpecifierNonArray.isMatrix())
2593 {
2594 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
2595 }
2596 // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
2597 return;
2598 default:
2599 break;
2600 }
2601
2602 // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
2603 // restrictions.
2604 bool typeContainsIntegers =
2605 (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
2606 type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
2607 bool extendedShaderTypes = mShaderVersion >= 320 ||
2608 isExtensionEnabled(TExtension::EXT_geometry_shader) ||
2609 isExtensionEnabled(TExtension::OES_geometry_shader) ||
2610 isExtensionEnabled(TExtension::EXT_tessellation_shader);
2611 if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut &&
2612 (!extendedShaderTypes || mShaderType == GL_FRAGMENT_SHADER))
2613 {
2614 error(qualifierLocation, "must use 'flat' interpolation here",
2615 getQualifierString(qualifier));
2616 }
2617
2618 if (type.getBasicType() == EbtStruct)
2619 {
2620 // ESSL 3.00 sections 4.3.4 and 4.3.6.
2621 // These restrictions are only implied by the ESSL 3.00 spec, but
2622 // the ESSL 3.10 spec lists these restrictions explicitly.
2623 if (type.isArray())
2624 {
2625 error(qualifierLocation, "cannot be an array of structures",
2626 getQualifierString(qualifier));
2627 }
2628 if (type.isStructureContainingArrays())
2629 {
2630 error(qualifierLocation, "cannot be a structure containing an array",
2631 getQualifierString(qualifier));
2632 }
2633 if (type.isStructureContainingType(EbtStruct))
2634 {
2635 error(qualifierLocation, "cannot be a structure containing a structure",
2636 getQualifierString(qualifier));
2637 }
2638 if (type.isStructureContainingType(EbtBool))
2639 {
2640 error(qualifierLocation, "cannot be a structure containing a bool",
2641 getQualifierString(qualifier));
2642 }
2643 }
2644 }
2645
checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase & qualifier)2646 void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
2647 {
2648 if (qualifier.getType() == QtStorage)
2649 {
2650 const TStorageQualifierWrapper &storageQualifier =
2651 static_cast<const TStorageQualifierWrapper &>(qualifier);
2652 if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
2653 !symbolTable.atGlobalLevel())
2654 {
2655 error(storageQualifier.getLine(),
2656 "Local variables can only use the const storage qualifier.",
2657 storageQualifier.getQualifierString());
2658 }
2659 }
2660 }
2661
checkMemoryQualifierIsNotSpecified(const TMemoryQualifier & memoryQualifier,const TSourceLoc & location)2662 void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
2663 const TSourceLoc &location)
2664 {
2665 const std::string reason(
2666 "Only allowed with shader storage blocks, variables declared within shader storage blocks "
2667 "and variables declared as image types.");
2668 if (memoryQualifier.readonly)
2669 {
2670 error(location, reason.c_str(), "readonly");
2671 }
2672 if (memoryQualifier.writeonly)
2673 {
2674 error(location, reason.c_str(), "writeonly");
2675 }
2676 if (memoryQualifier.coherent)
2677 {
2678 error(location, reason.c_str(), "coherent");
2679 }
2680 if (memoryQualifier.restrictQualifier)
2681 {
2682 error(location, reason.c_str(), "restrict");
2683 }
2684 if (memoryQualifier.volatileQualifier)
2685 {
2686 error(location, reason.c_str(), "volatile");
2687 }
2688 }
2689
2690 // Make sure there is no offset overlapping, and store the newly assigned offset to "type" in
2691 // intermediate tree.
checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend,const TSourceLoc & loc,TType * type)2692 void TParseContext::checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend,
2693 const TSourceLoc &loc,
2694 TType *type)
2695 {
2696 const size_t size = type->isArray() ? kAtomicCounterArrayStride * type->getArraySizeProduct()
2697 : kAtomicCounterSize;
2698 TLayoutQualifier layoutQualifier = type->getLayoutQualifier();
2699 auto &bindingState = mAtomicCounterBindingStates[layoutQualifier.binding];
2700 int offset;
2701 if (layoutQualifier.offset == -1 || forceAppend)
2702 {
2703 offset = bindingState.appendSpan(size);
2704 }
2705 else
2706 {
2707 offset = bindingState.insertSpan(layoutQualifier.offset, size);
2708 }
2709 if (offset == -1)
2710 {
2711 error(loc, "Offset overlapping", "atomic counter");
2712 return;
2713 }
2714 layoutQualifier.offset = offset;
2715 type->setLayoutQualifier(layoutQualifier);
2716 }
2717
checkAtomicCounterOffsetAlignment(const TSourceLoc & location,const TType & type)2718 void TParseContext::checkAtomicCounterOffsetAlignment(const TSourceLoc &location, const TType &type)
2719 {
2720 TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
2721
2722 // OpenGL ES 3.1 Table 6.5, Atomic counter offset must be a multiple of 4
2723 if (layoutQualifier.offset % 4 != 0)
2724 {
2725 error(location, "Offset must be multiple of 4", "atomic counter");
2726 }
2727 }
2728
checkGeometryShaderInputAndSetArraySize(const TSourceLoc & location,const ImmutableString & token,TType * type)2729 void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location,
2730 const ImmutableString &token,
2731 TType *type)
2732 {
2733 if (IsGeometryShaderInput(mShaderType, type->getQualifier()))
2734 {
2735 if (type->isArray() && type->getOutermostArraySize() == 0u)
2736 {
2737 // Set size for the unsized geometry shader inputs if they are declared after a valid
2738 // input primitive declaration.
2739 if (mGeometryShaderInputPrimitiveType != EptUndefined)
2740 {
2741 ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr);
2742 type->sizeOutermostUnsizedArray(
2743 symbolTable.getGlInVariableWithArraySize()->getType().getOutermostArraySize());
2744 }
2745 else
2746 {
2747 // [GLSL ES 3.2 SPEC Chapter 4.4.1.2]
2748 // An input can be declared without an array size if there is a previous layout
2749 // which specifies the size.
2750 error(location,
2751 "Missing a valid input primitive declaration before declaring an unsized "
2752 "array input",
2753 token);
2754 }
2755 }
2756 else if (type->isArray())
2757 {
2758 setGeometryShaderInputArraySize(type->getOutermostArraySize(), location);
2759 }
2760 else
2761 {
2762 error(location, "Geometry shader input variable must be declared as an array", token);
2763 }
2764 }
2765 }
2766
checkTessellationShaderUnsizedArraysAndSetSize(const TSourceLoc & location,const ImmutableString & token,TType * type)2767 void TParseContext::checkTessellationShaderUnsizedArraysAndSetSize(const TSourceLoc &location,
2768 const ImmutableString &token,
2769 TType *type)
2770 {
2771 TQualifier qualifier = type->getQualifier();
2772 if (!IsTessellationControlShaderOutput(mShaderType, qualifier) &&
2773 !IsTessellationControlShaderInput(mShaderType, qualifier) &&
2774 !IsTessellationEvaluationShaderInput(mShaderType, qualifier))
2775 {
2776 return;
2777 }
2778
2779 // Such variables must be declared as arrays or inside output blocks declared as arrays.
2780 if (!type->isArray())
2781 {
2782 error(location, "Tessellation interface variables must be declared as an array", token);
2783 return;
2784 }
2785
2786 // If a size is specified, it must match the maximum patch size.
2787 unsigned int outermostSize = type->getOutermostArraySize();
2788 if (outermostSize == 0u)
2789 {
2790 switch (qualifier)
2791 {
2792 case EvqTessControlIn:
2793 case EvqTessEvaluationIn:
2794 case EvqFlatIn:
2795 case EvqCentroidIn:
2796 case EvqSmoothIn:
2797 case EvqSampleIn:
2798 // Declaring an array size is optional. If no size is specified, it will be taken
2799 // from the implementation-dependent maximum patch size (gl_MaxPatchVertices).
2800 ASSERT(mMaxPatchVertices > 0);
2801 type->sizeOutermostUnsizedArray(mMaxPatchVertices);
2802 break;
2803 case EvqTessControlOut:
2804 case EvqFlatOut:
2805 case EvqCentroidOut:
2806 case EvqSmoothOut:
2807 case EvqSampleOut:
2808 // Declaring an array size is optional. If no size is specified, it will be taken
2809 // from output patch size declared in the shader.
2810 type->sizeOutermostUnsizedArray(mTessControlShaderOutputVertices);
2811 break;
2812 default:
2813 UNREACHABLE();
2814 break;
2815 }
2816 }
2817 else
2818 {
2819 if (IsTessellationControlShaderInput(mShaderType, qualifier) ||
2820 IsTessellationEvaluationShaderInput(mShaderType, qualifier))
2821 {
2822 if (outermostSize != static_cast<unsigned int>(mMaxPatchVertices))
2823 {
2824 error(
2825 location,
2826 "If a size is specified for a tessellation control or evaluation user-defined "
2827 "input variable, it must match the maximum patch size (gl_MaxPatchVertices).",
2828 token);
2829 }
2830 }
2831 else if (IsTessellationControlShaderOutput(mShaderType, qualifier))
2832 {
2833 if (outermostSize != static_cast<unsigned int>(mTessControlShaderOutputVertices) &&
2834 mTessControlShaderOutputVertices != 0)
2835 {
2836 error(location,
2837 "If a size is specified for a tessellation control user-defined per-vertex "
2838 "output variable, it must match the the number of vertices in the output "
2839 "patch.",
2840 token);
2841 }
2842 }
2843
2844 return;
2845 }
2846 }
2847
parseSingleDeclaration(TPublicType & publicType,const TSourceLoc & identifierOrTypeLocation,const ImmutableString & identifier)2848 TIntermDeclaration *TParseContext::parseSingleDeclaration(
2849 TPublicType &publicType,
2850 const TSourceLoc &identifierOrTypeLocation,
2851 const ImmutableString &identifier)
2852 {
2853 TType *type = new TType(publicType);
2854 if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) != 0 &&
2855 mDirectiveHandler.pragma().stdgl.invariantAll)
2856 {
2857 TQualifier qualifier = type->getQualifier();
2858
2859 // The directive handler has already taken care of rejecting invalid uses of this pragma
2860 // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
2861 // affected variable declarations:
2862 //
2863 // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
2864 // elsewhere, in TranslatorGLSL.)
2865 //
2866 // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
2867 // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
2868 // the way this is currently implemented we have to enable this compiler option before
2869 // parsing the shader and determining the shading language version it uses. If this were
2870 // implemented as a post-pass, the workaround could be more targeted.
2871 if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut)
2872 {
2873 type->setInvariant(true);
2874 }
2875 }
2876
2877 checkGeometryShaderInputAndSetArraySize(identifierOrTypeLocation, identifier, type);
2878 checkTessellationShaderUnsizedArraysAndSetSize(identifierOrTypeLocation, identifier, type);
2879
2880 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2881 identifierOrTypeLocation);
2882
2883 bool emptyDeclaration = (identifier == "");
2884 mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration;
2885
2886 TIntermSymbol *symbol = nullptr;
2887 if (emptyDeclaration)
2888 {
2889 emptyDeclarationErrorCheck(*type, identifierOrTypeLocation);
2890 // In most cases we don't need to create a symbol node for an empty declaration.
2891 // But if the empty declaration is declaring a struct type, the symbol node will store that.
2892 if (type->getBasicType() == EbtStruct)
2893 {
2894 TVariable *emptyVariable =
2895 new TVariable(&symbolTable, kEmptyImmutableString, type, SymbolType::Empty);
2896 symbol = new TIntermSymbol(emptyVariable);
2897 }
2898 else if (IsAtomicCounter(publicType.getBasicType()))
2899 {
2900 setAtomicCounterBindingDefaultOffset(publicType, identifierOrTypeLocation);
2901 }
2902 }
2903 else
2904 {
2905 nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
2906
2907 checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, type);
2908
2909 if (IsAtomicCounter(type->getBasicType()))
2910 {
2911 checkAtomicCounterOffsetDoesNotOverlap(false, identifierOrTypeLocation, type);
2912
2913 checkAtomicCounterOffsetAlignment(identifierOrTypeLocation, *type);
2914 }
2915
2916 TVariable *variable = nullptr;
2917 if (declareVariable(identifierOrTypeLocation, identifier, type, &variable))
2918 {
2919 symbol = new TIntermSymbol(variable);
2920 }
2921 }
2922
2923 TIntermDeclaration *declaration = new TIntermDeclaration();
2924 declaration->setLine(identifierOrTypeLocation);
2925 if (symbol)
2926 {
2927 symbol->setLine(identifierOrTypeLocation);
2928 declaration->appendDeclarator(symbol);
2929 }
2930 return declaration;
2931 }
2932
parseSingleArrayDeclaration(TPublicType & elementType,const TSourceLoc & identifierLocation,const ImmutableString & identifier,const TSourceLoc & indexLocation,const TVector<unsigned int> & arraySizes)2933 TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(
2934 TPublicType &elementType,
2935 const TSourceLoc &identifierLocation,
2936 const ImmutableString &identifier,
2937 const TSourceLoc &indexLocation,
2938 const TVector<unsigned int> &arraySizes)
2939 {
2940 mDeferredNonEmptyDeclarationErrorCheck = false;
2941
2942 declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier,
2943 identifierLocation);
2944
2945 nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
2946
2947 checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
2948
2949 TType *arrayType = new TType(elementType);
2950 arrayType->makeArrays(arraySizes);
2951
2952 checkArrayOfArraysInOut(indexLocation, elementType, *arrayType);
2953
2954 checkGeometryShaderInputAndSetArraySize(indexLocation, identifier, arrayType);
2955 checkTessellationShaderUnsizedArraysAndSetSize(indexLocation, identifier, arrayType);
2956
2957 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, arrayType);
2958
2959 if (IsAtomicCounter(arrayType->getBasicType()))
2960 {
2961 checkAtomicCounterOffsetDoesNotOverlap(false, identifierLocation, arrayType);
2962
2963 checkAtomicCounterOffsetAlignment(identifierLocation, *arrayType);
2964 }
2965
2966 TIntermDeclaration *declaration = new TIntermDeclaration();
2967 declaration->setLine(identifierLocation);
2968
2969 TVariable *variable = nullptr;
2970 if (declareVariable(identifierLocation, identifier, arrayType, &variable))
2971 {
2972 TIntermSymbol *symbol = new TIntermSymbol(variable);
2973 symbol->setLine(identifierLocation);
2974 declaration->appendDeclarator(symbol);
2975 }
2976
2977 return declaration;
2978 }
2979
parseSingleInitDeclaration(const TPublicType & publicType,const TSourceLoc & identifierLocation,const ImmutableString & identifier,const TSourceLoc & initLocation,TIntermTyped * initializer)2980 TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
2981 const TSourceLoc &identifierLocation,
2982 const ImmutableString &identifier,
2983 const TSourceLoc &initLocation,
2984 TIntermTyped *initializer)
2985 {
2986 mDeferredNonEmptyDeclarationErrorCheck = false;
2987
2988 declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
2989 identifierLocation);
2990
2991 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
2992
2993 TIntermDeclaration *declaration = new TIntermDeclaration();
2994 declaration->setLine(identifierLocation);
2995
2996 TIntermBinary *initNode = nullptr;
2997 TType *type = new TType(publicType);
2998 if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode))
2999 {
3000 if (initNode)
3001 {
3002 declaration->appendDeclarator(initNode);
3003 }
3004 else if (publicType.isStructSpecifier())
3005 {
3006 // The initialization got constant folded. If it's a struct, declare the struct anyway.
3007 TVariable *emptyVariable =
3008 new TVariable(&symbolTable, kEmptyImmutableString, type, SymbolType::Empty);
3009 TIntermSymbol *symbol = new TIntermSymbol(emptyVariable);
3010 symbol->setLine(publicType.getLine());
3011 declaration->appendDeclarator(symbol);
3012 }
3013 }
3014 return declaration;
3015 }
3016
parseSingleArrayInitDeclaration(TPublicType & elementType,const TSourceLoc & identifierLocation,const ImmutableString & identifier,const TSourceLoc & indexLocation,const TVector<unsigned int> & arraySizes,const TSourceLoc & initLocation,TIntermTyped * initializer)3017 TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
3018 TPublicType &elementType,
3019 const TSourceLoc &identifierLocation,
3020 const ImmutableString &identifier,
3021 const TSourceLoc &indexLocation,
3022 const TVector<unsigned int> &arraySizes,
3023 const TSourceLoc &initLocation,
3024 TIntermTyped *initializer)
3025 {
3026 mDeferredNonEmptyDeclarationErrorCheck = false;
3027
3028 declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier,
3029 identifierLocation);
3030
3031 nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
3032
3033 checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
3034
3035 TType *arrayType = new TType(elementType);
3036 arrayType->makeArrays(arraySizes);
3037
3038 TIntermDeclaration *declaration = new TIntermDeclaration();
3039 declaration->setLine(identifierLocation);
3040
3041 // initNode will correspond to the whole of "type b[n] = initializer".
3042 TIntermBinary *initNode = nullptr;
3043 if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
3044 {
3045 if (initNode)
3046 {
3047 declaration->appendDeclarator(initNode);
3048 }
3049 }
3050
3051 return declaration;
3052 }
3053
parseGlobalQualifierDeclaration(const TTypeQualifierBuilder & typeQualifierBuilder,const TSourceLoc & identifierLoc,const ImmutableString & identifier,const TSymbol * symbol)3054 TIntermGlobalQualifierDeclaration *TParseContext::parseGlobalQualifierDeclaration(
3055 const TTypeQualifierBuilder &typeQualifierBuilder,
3056 const TSourceLoc &identifierLoc,
3057 const ImmutableString &identifier,
3058 const TSymbol *symbol)
3059 {
3060 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
3061
3062 if (!typeQualifier.invariant && !typeQualifier.precise)
3063 {
3064 error(identifierLoc, "Expected invariant or precise", identifier);
3065 return nullptr;
3066 }
3067 if (typeQualifier.invariant && !checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
3068 {
3069 return nullptr;
3070 }
3071 if (!symbol)
3072 {
3073 error(identifierLoc, "undeclared identifier declared as invariant or precise", identifier);
3074 return nullptr;
3075 }
3076 if (!IsQualifierUnspecified(typeQualifier.qualifier))
3077 {
3078 error(identifierLoc, "invariant or precise declaration specifies qualifier",
3079 getQualifierString(typeQualifier.qualifier));
3080 }
3081 if (typeQualifier.precision != EbpUndefined)
3082 {
3083 error(identifierLoc, "invariant or precise declaration specifies precision",
3084 getPrecisionString(typeQualifier.precision));
3085 }
3086 if (!typeQualifier.layoutQualifier.isEmpty())
3087 {
3088 error(identifierLoc, "invariant or precise declaration specifies layout", "'layout'");
3089 }
3090
3091 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
3092 if (!variable)
3093 {
3094 return nullptr;
3095 }
3096 const TType &type = variable->getType();
3097
3098 checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
3099 typeQualifier.line);
3100 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
3101
3102 symbolTable.addInvariantVarying(*variable);
3103
3104 TIntermSymbol *intermSymbol = new TIntermSymbol(variable);
3105 intermSymbol->setLine(identifierLoc);
3106
3107 return new TIntermGlobalQualifierDeclaration(intermSymbol, typeQualifier.precise,
3108 identifierLoc);
3109 }
3110
parseDeclarator(TPublicType & publicType,const TSourceLoc & identifierLocation,const ImmutableString & identifier,TIntermDeclaration * declarationOut)3111 void TParseContext::parseDeclarator(TPublicType &publicType,
3112 const TSourceLoc &identifierLocation,
3113 const ImmutableString &identifier,
3114 TIntermDeclaration *declarationOut)
3115 {
3116 // If the declaration starting this declarator list was empty (example: int,), some checks were
3117 // not performed.
3118 if (mDeferredNonEmptyDeclarationErrorCheck)
3119 {
3120 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
3121 mDeferredNonEmptyDeclarationErrorCheck = false;
3122 }
3123
3124 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
3125
3126 TType *type = new TType(publicType);
3127
3128 checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, type);
3129 checkTessellationShaderUnsizedArraysAndSetSize(identifierLocation, identifier, type);
3130
3131 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, type);
3132
3133 if (IsAtomicCounter(type->getBasicType()))
3134 {
3135 checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, type);
3136
3137 checkAtomicCounterOffsetAlignment(identifierLocation, *type);
3138 }
3139
3140 TVariable *variable = nullptr;
3141 if (declareVariable(identifierLocation, identifier, type, &variable))
3142 {
3143 TIntermSymbol *symbol = new TIntermSymbol(variable);
3144 symbol->setLine(identifierLocation);
3145 declarationOut->appendDeclarator(symbol);
3146 }
3147 }
3148
parseArrayDeclarator(TPublicType & elementType,const TSourceLoc & identifierLocation,const ImmutableString & identifier,const TSourceLoc & arrayLocation,const TVector<unsigned int> & arraySizes,TIntermDeclaration * declarationOut)3149 void TParseContext::parseArrayDeclarator(TPublicType &elementType,
3150 const TSourceLoc &identifierLocation,
3151 const ImmutableString &identifier,
3152 const TSourceLoc &arrayLocation,
3153 const TVector<unsigned int> &arraySizes,
3154 TIntermDeclaration *declarationOut)
3155 {
3156 // If the declaration starting this declarator list was empty (example: int,), some checks were
3157 // not performed.
3158 if (mDeferredNonEmptyDeclarationErrorCheck)
3159 {
3160 nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
3161 mDeferredNonEmptyDeclarationErrorCheck = false;
3162 }
3163
3164 checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType);
3165
3166 if (checkIsValidTypeAndQualifierForArray(arrayLocation, elementType))
3167 {
3168 TType *arrayType = new TType(elementType);
3169 arrayType->makeArrays(arraySizes);
3170
3171 checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, arrayType);
3172 checkTessellationShaderUnsizedArraysAndSetSize(identifierLocation, identifier, arrayType);
3173
3174 checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, arrayType);
3175
3176 if (IsAtomicCounter(arrayType->getBasicType()))
3177 {
3178 checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, arrayType);
3179
3180 checkAtomicCounterOffsetAlignment(identifierLocation, *arrayType);
3181 }
3182
3183 TVariable *variable = nullptr;
3184 if (declareVariable(identifierLocation, identifier, arrayType, &variable))
3185 {
3186 TIntermSymbol *symbol = new TIntermSymbol(variable);
3187 symbol->setLine(identifierLocation);
3188 declarationOut->appendDeclarator(symbol);
3189 }
3190 }
3191 }
3192
parseInitDeclarator(const TPublicType & publicType,const TSourceLoc & identifierLocation,const ImmutableString & identifier,const TSourceLoc & initLocation,TIntermTyped * initializer,TIntermDeclaration * declarationOut)3193 void TParseContext::parseInitDeclarator(const TPublicType &publicType,
3194 const TSourceLoc &identifierLocation,
3195 const ImmutableString &identifier,
3196 const TSourceLoc &initLocation,
3197 TIntermTyped *initializer,
3198 TIntermDeclaration *declarationOut)
3199 {
3200 // If the declaration starting this declarator list was empty (example: int,), some checks were
3201 // not performed.
3202 if (mDeferredNonEmptyDeclarationErrorCheck)
3203 {
3204 nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
3205 mDeferredNonEmptyDeclarationErrorCheck = false;
3206 }
3207
3208 checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
3209
3210 TIntermBinary *initNode = nullptr;
3211 TType *type = new TType(publicType);
3212 if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode))
3213 {
3214 //
3215 // build the intermediate representation
3216 //
3217 if (initNode)
3218 {
3219 declarationOut->appendDeclarator(initNode);
3220 }
3221 }
3222 }
3223
parseArrayInitDeclarator(const TPublicType & elementType,const TSourceLoc & identifierLocation,const ImmutableString & identifier,const TSourceLoc & indexLocation,const TVector<unsigned int> & arraySizes,const TSourceLoc & initLocation,TIntermTyped * initializer,TIntermDeclaration * declarationOut)3224 void TParseContext::parseArrayInitDeclarator(const TPublicType &elementType,
3225 const TSourceLoc &identifierLocation,
3226 const ImmutableString &identifier,
3227 const TSourceLoc &indexLocation,
3228 const TVector<unsigned int> &arraySizes,
3229 const TSourceLoc &initLocation,
3230 TIntermTyped *initializer,
3231 TIntermDeclaration *declarationOut)
3232 {
3233 // If the declaration starting this declarator list was empty (example: int,), some checks were
3234 // not performed.
3235 if (mDeferredNonEmptyDeclarationErrorCheck)
3236 {
3237 nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
3238 mDeferredNonEmptyDeclarationErrorCheck = false;
3239 }
3240
3241 checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType);
3242
3243 checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
3244
3245 TType *arrayType = new TType(elementType);
3246 arrayType->makeArrays(arraySizes);
3247
3248 // initNode will correspond to the whole of "b[n] = initializer".
3249 TIntermBinary *initNode = nullptr;
3250 if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
3251 {
3252 if (initNode)
3253 {
3254 declarationOut->appendDeclarator(initNode);
3255 }
3256 }
3257 }
3258
addEmptyStatement(const TSourceLoc & location)3259 TIntermNode *TParseContext::addEmptyStatement(const TSourceLoc &location)
3260 {
3261 // It's simpler to parse an empty statement as a constant expression rather than having a
3262 // different type of node just for empty statements, that will be pruned from the AST anyway.
3263 TIntermNode *node = CreateZeroNode(TType(EbtInt, EbpMedium));
3264 node->setLine(location);
3265 return node;
3266 }
3267
setAtomicCounterBindingDefaultOffset(const TPublicType & publicType,const TSourceLoc & location)3268 void TParseContext::setAtomicCounterBindingDefaultOffset(const TPublicType &publicType,
3269 const TSourceLoc &location)
3270 {
3271 const TLayoutQualifier &layoutQualifier = publicType.layoutQualifier;
3272 checkAtomicCounterBindingIsValid(location, layoutQualifier.binding);
3273 if (layoutQualifier.binding == -1 || layoutQualifier.offset == -1)
3274 {
3275 error(location, "Requires both binding and offset", "layout");
3276 return;
3277 }
3278 mAtomicCounterBindingStates[layoutQualifier.binding].setDefaultOffset(layoutQualifier.offset);
3279 }
3280
parseDefaultPrecisionQualifier(const TPrecision precision,const TPublicType & type,const TSourceLoc & loc)3281 void TParseContext::parseDefaultPrecisionQualifier(const TPrecision precision,
3282 const TPublicType &type,
3283 const TSourceLoc &loc)
3284 {
3285 if ((precision == EbpHigh) && (getShaderType() == GL_FRAGMENT_SHADER) &&
3286 !getFragmentPrecisionHigh())
3287 {
3288 error(loc, "precision is not supported in fragment shader", "highp");
3289 }
3290
3291 if (!CanSetDefaultPrecisionOnType(type))
3292 {
3293 error(loc, "illegal type argument for default precision qualifier",
3294 getBasicString(type.getBasicType()));
3295 return;
3296 }
3297 symbolTable.setDefaultPrecision(type.getBasicType(), precision);
3298 }
3299
checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier & typeQualifier)3300 bool TParseContext::checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier)
3301 {
3302 switch (typeQualifier.layoutQualifier.primitiveType)
3303 {
3304 case EptLines:
3305 case EptLinesAdjacency:
3306 case EptTriangles:
3307 case EptTrianglesAdjacency:
3308 return typeQualifier.qualifier == EvqGeometryIn;
3309
3310 case EptLineStrip:
3311 case EptTriangleStrip:
3312 return typeQualifier.qualifier == EvqGeometryOut;
3313
3314 case EptPoints:
3315 return true;
3316
3317 default:
3318 UNREACHABLE();
3319 return false;
3320 }
3321 }
3322
setGeometryShaderInputArraySize(unsigned int inputArraySize,const TSourceLoc & line)3323 void TParseContext::setGeometryShaderInputArraySize(unsigned int inputArraySize,
3324 const TSourceLoc &line)
3325 {
3326 if (!symbolTable.setGlInArraySize(inputArraySize))
3327 {
3328 error(line,
3329 "Array size or input primitive declaration doesn't match the size of earlier sized "
3330 "array inputs.",
3331 "layout");
3332 }
3333 mGeometryInputArraySize = inputArraySize;
3334 }
3335
parseGeometryShaderInputLayoutQualifier(const TTypeQualifier & typeQualifier)3336 bool TParseContext::parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier)
3337 {
3338 ASSERT(typeQualifier.qualifier == EvqGeometryIn);
3339
3340 const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
3341
3342 if (layoutQualifier.maxVertices != -1)
3343 {
3344 error(typeQualifier.line,
3345 "max_vertices can only be declared in 'out' layout in a geometry shader", "layout");
3346 return false;
3347 }
3348
3349 // Set mGeometryInputPrimitiveType if exists
3350 if (layoutQualifier.primitiveType != EptUndefined)
3351 {
3352 if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier))
3353 {
3354 error(typeQualifier.line, "invalid primitive type for 'in' layout", "layout");
3355 return false;
3356 }
3357
3358 if (mGeometryShaderInputPrimitiveType == EptUndefined)
3359 {
3360 mGeometryShaderInputPrimitiveType = layoutQualifier.primitiveType;
3361 setGeometryShaderInputArraySize(
3362 GetGeometryShaderInputArraySize(mGeometryShaderInputPrimitiveType),
3363 typeQualifier.line);
3364 }
3365 else if (mGeometryShaderInputPrimitiveType != layoutQualifier.primitiveType)
3366 {
3367 error(typeQualifier.line, "primitive doesn't match earlier input primitive declaration",
3368 "layout");
3369 return false;
3370 }
3371 }
3372
3373 // Set mGeometryInvocations if exists
3374 if (layoutQualifier.invocations > 0)
3375 {
3376 if (mGeometryShaderInvocations == 0)
3377 {
3378 mGeometryShaderInvocations = layoutQualifier.invocations;
3379 }
3380 else if (mGeometryShaderInvocations != layoutQualifier.invocations)
3381 {
3382 error(typeQualifier.line, "invocations contradicts to the earlier declaration",
3383 "layout");
3384 return false;
3385 }
3386 }
3387
3388 return true;
3389 }
3390
parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier & typeQualifier)3391 bool TParseContext::parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier)
3392 {
3393 ASSERT(typeQualifier.qualifier == EvqGeometryOut);
3394
3395 const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
3396
3397 if (layoutQualifier.invocations > 0)
3398 {
3399 error(typeQualifier.line,
3400 "invocations can only be declared in 'in' layout in a geometry shader", "layout");
3401 return false;
3402 }
3403
3404 // Set mGeometryOutputPrimitiveType if exists
3405 if (layoutQualifier.primitiveType != EptUndefined)
3406 {
3407 if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier))
3408 {
3409 error(typeQualifier.line, "invalid primitive type for 'out' layout", "layout");
3410 return false;
3411 }
3412
3413 if (mGeometryShaderOutputPrimitiveType == EptUndefined)
3414 {
3415 mGeometryShaderOutputPrimitiveType = layoutQualifier.primitiveType;
3416 }
3417 else if (mGeometryShaderOutputPrimitiveType != layoutQualifier.primitiveType)
3418 {
3419 error(typeQualifier.line,
3420 "primitive doesn't match earlier output primitive declaration", "layout");
3421 return false;
3422 }
3423 }
3424
3425 // Set mGeometryMaxVertices if exists
3426 if (layoutQualifier.maxVertices > -1)
3427 {
3428 if (mGeometryShaderMaxVertices == -1)
3429 {
3430 mGeometryShaderMaxVertices = layoutQualifier.maxVertices;
3431 }
3432 else if (mGeometryShaderMaxVertices != layoutQualifier.maxVertices)
3433 {
3434 error(typeQualifier.line, "max_vertices contradicts to the earlier declaration",
3435 "layout");
3436 return false;
3437 }
3438 }
3439
3440 return true;
3441 }
3442
parseTessControlShaderOutputLayoutQualifier(const TTypeQualifier & typeQualifier)3443 bool TParseContext::parseTessControlShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier)
3444 {
3445 ASSERT(typeQualifier.qualifier == EvqTessControlOut);
3446
3447 const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
3448
3449 if (layoutQualifier.vertices == 0)
3450 {
3451 error(typeQualifier.line, "No vertices specified", "layout");
3452 return false;
3453 }
3454
3455 // Set mTessControlShaderOutputVertices if exists
3456 if (mTessControlShaderOutputVertices == 0)
3457 {
3458 mTessControlShaderOutputVertices = layoutQualifier.vertices;
3459 }
3460 else
3461 {
3462 error(typeQualifier.line, "Duplicated vertices specified", "layout");
3463 }
3464 return true;
3465 }
3466
parseTessEvaluationShaderInputLayoutQualifier(const TTypeQualifier & typeQualifier)3467 bool TParseContext::parseTessEvaluationShaderInputLayoutQualifier(
3468 const TTypeQualifier &typeQualifier)
3469 {
3470 ASSERT(typeQualifier.qualifier == EvqTessEvaluationIn);
3471
3472 const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
3473
3474 // Set mTessEvaluationShaderInputPrimitiveType if exists
3475 if (layoutQualifier.tesPrimitiveType != EtetUndefined)
3476 {
3477 if (mTessEvaluationShaderInputPrimitiveType == EtetUndefined)
3478 {
3479 mTessEvaluationShaderInputPrimitiveType = layoutQualifier.tesPrimitiveType;
3480 }
3481 else
3482 {
3483 error(typeQualifier.line, "Duplicated primitive type declaration", "layout");
3484 }
3485 }
3486 // Set mTessEvaluationShaderVertexSpacingType if exists
3487 if (layoutQualifier.tesVertexSpacingType != EtetUndefined)
3488 {
3489 if (mTessEvaluationShaderInputVertexSpacingType == EtetUndefined)
3490 {
3491 mTessEvaluationShaderInputVertexSpacingType = layoutQualifier.tesVertexSpacingType;
3492 }
3493 else
3494 {
3495 error(typeQualifier.line, "Duplicated vertex spacing declaration", "layout");
3496 }
3497 }
3498 // Set mTessEvaluationShaderInputOrderingType if exists
3499 if (layoutQualifier.tesOrderingType != EtetUndefined)
3500 {
3501 if (mTessEvaluationShaderInputOrderingType == EtetUndefined)
3502 {
3503 mTessEvaluationShaderInputOrderingType = layoutQualifier.tesOrderingType;
3504 }
3505 else
3506 {
3507 error(typeQualifier.line, "Duplicated ordering declaration", "layout");
3508 }
3509 }
3510 // Set mTessEvaluationShaderInputPointType if exists
3511 if (layoutQualifier.tesPointType != EtetUndefined)
3512 {
3513 if (mTessEvaluationShaderInputPointType == EtetUndefined)
3514 {
3515 mTessEvaluationShaderInputPointType = layoutQualifier.tesPointType;
3516 }
3517 else
3518 {
3519 error(typeQualifier.line, "Duplicated point type declaration", "layout");
3520 }
3521 }
3522
3523 return true;
3524 }
3525
parseGlobalLayoutQualifier(const TTypeQualifierBuilder & typeQualifierBuilder)3526 void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
3527 {
3528 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
3529 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
3530
3531 checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
3532 typeQualifier.line);
3533
3534 // It should never be the case, but some strange parser errors can send us here.
3535 if (layoutQualifier.isEmpty())
3536 {
3537 error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
3538 return;
3539 }
3540
3541 if (!layoutQualifier.isCombinationValid())
3542 {
3543 error(typeQualifier.line, "invalid layout qualifier combination", "layout");
3544 return;
3545 }
3546
3547 checkIndexIsNotSpecified(typeQualifier.line, layoutQualifier.index);
3548
3549 checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);
3550
3551 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
3552
3553 checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
3554
3555 checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv);
3556
3557 checkOffsetIsNotSpecified(typeQualifier.line, layoutQualifier.offset);
3558
3559 checkStd430IsForShaderStorageBlock(typeQualifier.line, layoutQualifier.blockStorage,
3560 typeQualifier.qualifier);
3561
3562 if (typeQualifier.qualifier != EvqFragmentIn)
3563 {
3564 checkEarlyFragmentTestsIsNotSpecified(typeQualifier.line,
3565 layoutQualifier.earlyFragmentTests);
3566 }
3567
3568 if (typeQualifier.qualifier == EvqComputeIn)
3569 {
3570 if (mComputeShaderLocalSizeDeclared &&
3571 !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
3572 {
3573 error(typeQualifier.line, "Work group size does not match the previous declaration",
3574 "layout");
3575 return;
3576 }
3577
3578 if (mShaderVersion < 310)
3579 {
3580 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
3581 return;
3582 }
3583
3584 if (!layoutQualifier.localSize.isAnyValueSet())
3585 {
3586 error(typeQualifier.line, "No local work group size specified", "layout");
3587 return;
3588 }
3589
3590 const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
3591 symbolTable.findBuiltIn(ImmutableString("gl_MaxComputeWorkGroupSize"), mShaderVersion));
3592
3593 const TConstantUnion *maxComputeWorkGroupSizeData =
3594 maxComputeWorkGroupSize->getConstPointer();
3595
3596 for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
3597 {
3598 if (layoutQualifier.localSize[i] != -1)
3599 {
3600 mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
3601 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
3602 if (mComputeShaderLocalSize[i] < 1 ||
3603 mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
3604 {
3605 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
3606 reasonStream << "invalid value: Value must be at least 1 and no greater than "
3607 << maxComputeWorkGroupSizeValue;
3608 const std::string &reason = reasonStream.str();
3609
3610 error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
3611 return;
3612 }
3613 }
3614 }
3615
3616 mComputeShaderLocalSizeDeclared = true;
3617 }
3618 else if (typeQualifier.qualifier == EvqGeometryIn)
3619 {
3620 if (mShaderVersion < 310)
3621 {
3622 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
3623 return;
3624 }
3625
3626 if (!parseGeometryShaderInputLayoutQualifier(typeQualifier))
3627 {
3628 return;
3629 }
3630 }
3631 else if (typeQualifier.qualifier == EvqGeometryOut)
3632 {
3633 if (mShaderVersion < 310)
3634 {
3635 error(typeQualifier.line, "out type qualifier supported in GLSL ES 3.10 only",
3636 "layout");
3637 return;
3638 }
3639
3640 if (!parseGeometryShaderOutputLayoutQualifier(typeQualifier))
3641 {
3642 return;
3643 }
3644 }
3645 else if (anyMultiviewExtensionAvailable() && typeQualifier.qualifier == EvqVertexIn)
3646 {
3647 // This error is only specified in WebGL, but tightens unspecified behavior in the native
3648 // specification.
3649 if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
3650 {
3651 error(typeQualifier.line, "Number of views does not match the previous declaration",
3652 "layout");
3653 return;
3654 }
3655
3656 if (layoutQualifier.numViews == -1)
3657 {
3658 error(typeQualifier.line, "No num_views specified", "layout");
3659 return;
3660 }
3661
3662 if (layoutQualifier.numViews > mMaxNumViews)
3663 {
3664 error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
3665 "layout");
3666 return;
3667 }
3668
3669 mNumViews = layoutQualifier.numViews;
3670 }
3671 else if (typeQualifier.qualifier == EvqFragmentIn)
3672 {
3673 if (mShaderVersion < 310)
3674 {
3675 error(typeQualifier.line,
3676 "in type qualifier without variable declaration supported in GLSL ES 3.10 and "
3677 "after",
3678 "layout");
3679 return;
3680 }
3681
3682 if (!layoutQualifier.earlyFragmentTests)
3683 {
3684 error(typeQualifier.line,
3685 "only early_fragment_tests is allowed as layout qualifier when not declaring a "
3686 "variable",
3687 "layout");
3688 return;
3689 }
3690
3691 mEarlyFragmentTestsSpecified = true;
3692 }
3693 else if (typeQualifier.qualifier == EvqTessControlOut)
3694 {
3695 if (mShaderVersion < 310)
3696 {
3697 error(typeQualifier.line, "out type qualifier supported in GLSL ES 3.10 and after",
3698 "layout");
3699 return;
3700 }
3701
3702 if (!parseTessControlShaderOutputLayoutQualifier(typeQualifier))
3703 {
3704 return;
3705 }
3706 }
3707 else if (typeQualifier.qualifier == EvqTessEvaluationIn)
3708 {
3709 if (mShaderVersion < 310)
3710 {
3711 error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 and after",
3712 "layout");
3713 return;
3714 }
3715
3716 if (!parseTessEvaluationShaderInputLayoutQualifier(typeQualifier))
3717 {
3718 return;
3719 }
3720 }
3721 else
3722 {
3723 if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
3724 {
3725 return;
3726 }
3727
3728 if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer)
3729 {
3730 error(typeQualifier.line, "invalid qualifier: global layout can only be set for blocks",
3731 getQualifierString(typeQualifier.qualifier));
3732 return;
3733 }
3734
3735 if (mShaderVersion < 300)
3736 {
3737 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and after",
3738 "layout");
3739 return;
3740 }
3741
3742 checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
3743
3744 if (layoutQualifier.matrixPacking != EmpUnspecified)
3745 {
3746 if (typeQualifier.qualifier == EvqUniform)
3747 {
3748 mDefaultUniformMatrixPacking = layoutQualifier.matrixPacking;
3749 }
3750 else if (typeQualifier.qualifier == EvqBuffer)
3751 {
3752 mDefaultBufferMatrixPacking = layoutQualifier.matrixPacking;
3753 }
3754 }
3755
3756 if (layoutQualifier.blockStorage != EbsUnspecified)
3757 {
3758 if (typeQualifier.qualifier == EvqUniform)
3759 {
3760 mDefaultUniformBlockStorage = layoutQualifier.blockStorage;
3761 }
3762 else if (typeQualifier.qualifier == EvqBuffer)
3763 {
3764 mDefaultBufferBlockStorage = layoutQualifier.blockStorage;
3765 }
3766 }
3767 }
3768 }
3769
createPrototypeNodeFromFunction(const TFunction & function,const TSourceLoc & location,bool insertParametersToSymbolTable)3770 TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
3771 const TFunction &function,
3772 const TSourceLoc &location,
3773 bool insertParametersToSymbolTable)
3774 {
3775 checkIsNotReserved(location, function.name());
3776
3777 TIntermFunctionPrototype *prototype = new TIntermFunctionPrototype(&function);
3778 prototype->setLine(location);
3779
3780 for (size_t i = 0; i < function.getParamCount(); i++)
3781 {
3782 const TVariable *param = function.getParam(i);
3783
3784 // If the parameter has no name, it's not an error, just don't add it to symbol table (could
3785 // be used for unused args).
3786 if (param->symbolType() != SymbolType::Empty)
3787 {
3788 if (insertParametersToSymbolTable)
3789 {
3790 if (!symbolTable.declare(const_cast<TVariable *>(param)))
3791 {
3792 error(location, "redefinition", param->name());
3793 }
3794 }
3795 // Unsized type of a named parameter should have already been checked and sanitized.
3796 ASSERT(!param->getType().isUnsizedArray());
3797 }
3798 else
3799 {
3800 if (param->getType().isUnsizedArray())
3801 {
3802 error(location, "function parameter array must be sized at compile time", "[]");
3803 // We don't need to size the arrays since the parameter is unnamed and hence
3804 // inaccessible.
3805 }
3806 }
3807 }
3808 return prototype;
3809 }
3810
addFunctionPrototypeDeclaration(const TFunction & parsedFunction,const TSourceLoc & location)3811 TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
3812 const TFunction &parsedFunction,
3813 const TSourceLoc &location)
3814 {
3815 // Note: function found from the symbol table could be the same as parsedFunction if this is the
3816 // first declaration. Either way the instance in the symbol table is used to track whether the
3817 // function is declared multiple times.
3818 bool hadPrototypeDeclaration = false;
3819 const TFunction *function = symbolTable.markFunctionHasPrototypeDeclaration(
3820 parsedFunction.getMangledName(), &hadPrototypeDeclaration);
3821
3822 if (hadPrototypeDeclaration && mShaderVersion == 100)
3823 {
3824 // ESSL 1.00.17 section 4.2.7.
3825 // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
3826 error(location, "duplicate function prototype declarations are not allowed", "function");
3827 }
3828
3829 TIntermFunctionPrototype *prototype =
3830 createPrototypeNodeFromFunction(*function, location, false);
3831
3832 symbolTable.pop();
3833
3834 if (!symbolTable.atGlobalLevel())
3835 {
3836 // ESSL 3.00.4 section 4.2.4.
3837 error(location, "local function prototype declarations are not allowed", "function");
3838 }
3839
3840 return prototype;
3841 }
3842
addFunctionDefinition(TIntermFunctionPrototype * functionPrototype,TIntermBlock * functionBody,const TSourceLoc & location)3843 TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
3844 TIntermFunctionPrototype *functionPrototype,
3845 TIntermBlock *functionBody,
3846 const TSourceLoc &location)
3847 {
3848 // Undo push at end of parseFunctionDefinitionHeader() below for ESSL1.00 case
3849 if (mFunctionBodyNewScope)
3850 {
3851 mFunctionBodyNewScope = false;
3852 symbolTable.pop();
3853 }
3854
3855 // Check that non-void functions have at least one return statement.
3856 if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
3857 {
3858 error(location,
3859 "function does not return a value:", functionPrototype->getFunction()->name());
3860 }
3861
3862 if (functionBody == nullptr)
3863 {
3864 functionBody = new TIntermBlock();
3865 functionBody->setLine(location);
3866 }
3867 TIntermFunctionDefinition *functionNode =
3868 new TIntermFunctionDefinition(functionPrototype, functionBody);
3869 functionNode->setLine(location);
3870
3871 symbolTable.pop();
3872 return functionNode;
3873 }
3874
parseFunctionDefinitionHeader(const TSourceLoc & location,const TFunction * function,TIntermFunctionPrototype ** prototypeOut)3875 void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
3876 const TFunction *function,
3877 TIntermFunctionPrototype **prototypeOut)
3878 {
3879 ASSERT(function);
3880
3881 bool wasDefined = false;
3882 function = symbolTable.setFunctionParameterNamesFromDefinition(function, &wasDefined);
3883 if (wasDefined)
3884 {
3885 error(location, "function already has a body", function->name());
3886 }
3887
3888 // Remember the return type for later checking for return statements.
3889 mCurrentFunctionType = &(function->getReturnType());
3890 mFunctionReturnsValue = false;
3891
3892 *prototypeOut = createPrototypeNodeFromFunction(*function, location, true);
3893 setLoopNestingLevel(0);
3894
3895 // ESSL 1.00 spec allows for variable in function body to redefine parameter
3896 if (IsSpecWithFunctionBodyNewScope(mShaderSpec, mShaderVersion))
3897 {
3898 mFunctionBodyNewScope = true;
3899 symbolTable.push();
3900 }
3901 }
3902
parseFunctionDeclarator(const TSourceLoc & location,TFunction * function)3903 TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
3904 {
3905 //
3906 // We don't know at this point whether this is a function definition or a prototype.
3907 // The definition production code will check for redefinitions.
3908 // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
3909 //
3910
3911 for (size_t i = 0u; i < function->getParamCount(); ++i)
3912 {
3913 const TVariable *param = function->getParam(i);
3914 if (param->getType().isStructSpecifier())
3915 {
3916 // ESSL 3.00.6 section 12.10.
3917 error(location, "Function parameter type cannot be a structure definition",
3918 function->name());
3919 }
3920 }
3921
3922 if (getShaderVersion() >= 300)
3923 {
3924
3925 if (symbolTable.isUnmangledBuiltInName(function->name(), getShaderVersion(),
3926 extensionBehavior()))
3927 {
3928 // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as
3929 // functions. Therefore overloading or redefining builtin functions is an error.
3930 error(location, "Name of a built-in function cannot be redeclared as function",
3931 function->name());
3932 }
3933 }
3934 else
3935 {
3936 // ESSL 1.00.17 section 4.2.6: built-ins can be overloaded but not redefined. We assume that
3937 // this applies to redeclarations as well.
3938 const TSymbol *builtIn =
3939 symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
3940 if (builtIn)
3941 {
3942 error(location, "built-in functions cannot be redefined", function->name());
3943 }
3944 }
3945
3946 // Return types and parameter qualifiers must match in all redeclarations, so those are checked
3947 // here.
3948 const TFunction *prevDec =
3949 static_cast<const TFunction *>(symbolTable.findGlobal(function->getMangledName()));
3950 if (prevDec)
3951 {
3952 if (prevDec->getReturnType() != function->getReturnType())
3953 {
3954 error(location, "function must have the same return type in all of its declarations",
3955 function->getReturnType().getBasicString());
3956 }
3957 for (size_t i = 0; i < prevDec->getParamCount(); ++i)
3958 {
3959 if (prevDec->getParam(i)->getType().getQualifier() !=
3960 function->getParam(i)->getType().getQualifier())
3961 {
3962 error(location,
3963 "function must have the same parameter qualifiers in all of its declarations",
3964 function->getParam(i)->getType().getQualifierString());
3965 }
3966 }
3967 }
3968
3969 // Check for previously declared variables using the same name.
3970 const TSymbol *prevSym = symbolTable.find(function->name(), getShaderVersion());
3971 bool insertUnmangledName = true;
3972 if (prevSym)
3973 {
3974 if (!prevSym->isFunction())
3975 {
3976 error(location, "redefinition of a function", function->name());
3977 }
3978 insertUnmangledName = false;
3979 }
3980 // Parsing is at the inner scope level of the function's arguments and body statement at this
3981 // point, but declareUserDefinedFunction takes care of declaring the function at the global
3982 // scope.
3983 symbolTable.declareUserDefinedFunction(function, insertUnmangledName);
3984
3985 // Raise error message if main function takes any parameters or return anything other than void
3986 if (function->isMain())
3987 {
3988 if (function->getParamCount() > 0)
3989 {
3990 error(location, "function cannot take any parameter(s)", "main");
3991 }
3992 if (function->getReturnType().getBasicType() != EbtVoid)
3993 {
3994 error(location, "main function cannot return a value",
3995 function->getReturnType().getBasicString());
3996 }
3997 }
3998
3999 //
4000 // If this is a redeclaration, it could also be a definition, in which case, we want to use the
4001 // variable names from this one, and not the one that's
4002 // being redeclared. So, pass back up this declaration, not the one in the symbol table.
4003 //
4004 return function;
4005 }
4006
parseFunctionHeader(const TPublicType & type,const ImmutableString & name,const TSourceLoc & location)4007 TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
4008 const ImmutableString &name,
4009 const TSourceLoc &location)
4010 {
4011 if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
4012 {
4013 error(location, "no qualifiers allowed for function return",
4014 getQualifierString(type.qualifier));
4015 }
4016 if (!type.layoutQualifier.isEmpty())
4017 {
4018 error(location, "no qualifiers allowed for function return", "layout");
4019 }
4020 // make sure an opaque type is not involved as well...
4021 std::string reason(getBasicString(type.getBasicType()));
4022 reason += "s can't be function return values";
4023 checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str());
4024 if (mShaderVersion < 300)
4025 {
4026 // Array return values are forbidden, but there's also no valid syntax for declaring array
4027 // return values in ESSL 1.00.
4028 ASSERT(!type.isArray() || mDiagnostics->numErrors() > 0);
4029
4030 if (type.isStructureContainingArrays())
4031 {
4032 // ESSL 1.00.17 section 6.1 Function Definitions
4033 TInfoSinkBase typeString;
4034 typeString << TType(type);
4035 error(location, "structures containing arrays can't be function return values",
4036 typeString.c_str());
4037 }
4038 }
4039
4040 // Add the function as a prototype after parsing it (we do not support recursion)
4041 return new TFunction(&symbolTable, name, SymbolType::UserDefined, new TType(type), false);
4042 }
4043
addNonConstructorFunc(const ImmutableString & name,const TSymbol * symbol)4044 TFunctionLookup *TParseContext::addNonConstructorFunc(const ImmutableString &name,
4045 const TSymbol *symbol)
4046 {
4047 return TFunctionLookup::CreateFunctionCall(name, symbol);
4048 }
4049
addConstructorFunc(const TPublicType & publicType)4050 TFunctionLookup *TParseContext::addConstructorFunc(const TPublicType &publicType)
4051 {
4052 if (mShaderVersion < 300 && publicType.isArray())
4053 {
4054 error(publicType.getLine(), "array constructor supported in GLSL ES 3.00 and above only",
4055 "[]");
4056 }
4057 if (publicType.isStructSpecifier())
4058 {
4059 error(publicType.getLine(), "constructor can't be a structure definition",
4060 getBasicString(publicType.getBasicType()));
4061 }
4062
4063 TType *type = new TType(publicType);
4064 if (!type->canBeConstructed())
4065 {
4066 error(publicType.getLine(), "cannot construct this type",
4067 getBasicString(publicType.getBasicType()));
4068 type->setBasicType(EbtFloat);
4069 }
4070 return TFunctionLookup::CreateConstructor(type);
4071 }
4072
checkIsNotUnsizedArray(const TSourceLoc & line,const char * errorMessage,const ImmutableString & token,TType * arrayType)4073 void TParseContext::checkIsNotUnsizedArray(const TSourceLoc &line,
4074 const char *errorMessage,
4075 const ImmutableString &token,
4076 TType *arrayType)
4077 {
4078 if (arrayType->isUnsizedArray())
4079 {
4080 error(line, errorMessage, token);
4081 arrayType->sizeUnsizedArrays(TSpan<const unsigned int>());
4082 }
4083 }
4084
parseParameterDeclarator(TType * type,const ImmutableString & name,const TSourceLoc & nameLoc)4085 TParameter TParseContext::parseParameterDeclarator(TType *type,
4086 const ImmutableString &name,
4087 const TSourceLoc &nameLoc)
4088 {
4089 ASSERT(type);
4090 checkIsNotUnsizedArray(nameLoc, "function parameter array must specify a size", name, type);
4091 if (type->getBasicType() == EbtVoid)
4092 {
4093 error(nameLoc, "illegal use of type 'void'", name);
4094 }
4095 checkIsNotReserved(nameLoc, name);
4096 TParameter param = {name.data(), type};
4097 return param;
4098 }
4099
parseParameterDeclarator(const TPublicType & publicType,const ImmutableString & name,const TSourceLoc & nameLoc)4100 TParameter TParseContext::parseParameterDeclarator(const TPublicType &publicType,
4101 const ImmutableString &name,
4102 const TSourceLoc &nameLoc)
4103 {
4104 TType *type = new TType(publicType);
4105 return parseParameterDeclarator(type, name, nameLoc);
4106 }
4107
parseParameterArrayDeclarator(const ImmutableString & name,const TSourceLoc & nameLoc,const TVector<unsigned int> & arraySizes,const TSourceLoc & arrayLoc,TPublicType * elementType)4108 TParameter TParseContext::parseParameterArrayDeclarator(const ImmutableString &name,
4109 const TSourceLoc &nameLoc,
4110 const TVector<unsigned int> &arraySizes,
4111 const TSourceLoc &arrayLoc,
4112 TPublicType *elementType)
4113 {
4114 checkArrayElementIsNotArray(arrayLoc, *elementType);
4115 TType *arrayType = new TType(*elementType);
4116 arrayType->makeArrays(arraySizes);
4117 return parseParameterDeclarator(arrayType, name, nameLoc);
4118 }
4119
checkUnsizedArrayConstructorArgumentDimensionality(const TIntermSequence & arguments,TType type,const TSourceLoc & line)4120 bool TParseContext::checkUnsizedArrayConstructorArgumentDimensionality(
4121 const TIntermSequence &arguments,
4122 TType type,
4123 const TSourceLoc &line)
4124 {
4125 if (arguments.empty())
4126 {
4127 error(line, "implicitly sized array constructor must have at least one argument", "[]");
4128 return false;
4129 }
4130 for (TIntermNode *arg : arguments)
4131 {
4132 const TIntermTyped *element = arg->getAsTyped();
4133 ASSERT(element);
4134 size_t dimensionalityFromElement = element->getType().getNumArraySizes() + 1u;
4135 if (dimensionalityFromElement > type.getNumArraySizes())
4136 {
4137 error(line, "constructing from a non-dereferenced array", "constructor");
4138 return false;
4139 }
4140 else if (dimensionalityFromElement < type.getNumArraySizes())
4141 {
4142 if (dimensionalityFromElement == 1u)
4143 {
4144 error(line, "implicitly sized array of arrays constructor argument is not an array",
4145 "constructor");
4146 }
4147 else
4148 {
4149 error(line,
4150 "implicitly sized array of arrays constructor argument dimensionality is too "
4151 "low",
4152 "constructor");
4153 }
4154 return false;
4155 }
4156 }
4157 return true;
4158 }
4159
4160 // This function is used to test for the correctness of the parameters passed to various constructor
4161 // functions and also convert them to the right datatype if it is allowed and required.
4162 //
4163 // Returns a node to add to the tree regardless of if an error was generated or not.
4164 //
addConstructor(TFunctionLookup * fnCall,const TSourceLoc & line)4165 TIntermTyped *TParseContext::addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line)
4166 {
4167 TType type = fnCall->constructorType();
4168 TIntermSequence &arguments = fnCall->arguments();
4169 if (type.isUnsizedArray())
4170 {
4171 if (!checkUnsizedArrayConstructorArgumentDimensionality(arguments, type, line))
4172 {
4173 type.sizeUnsizedArrays(TSpan<const unsigned int>());
4174 return CreateZeroNode(type);
4175 }
4176 TIntermTyped *firstElement = arguments.at(0)->getAsTyped();
4177 ASSERT(firstElement);
4178 if (type.getOutermostArraySize() == 0u)
4179 {
4180 type.sizeOutermostUnsizedArray(static_cast<unsigned int>(arguments.size()));
4181 }
4182 for (size_t i = 0; i < firstElement->getType().getNumArraySizes(); ++i)
4183 {
4184 if (type.getArraySizes()[i] == 0u)
4185 {
4186 type.setArraySize(i, firstElement->getType().getArraySizes()[i]);
4187 }
4188 }
4189 ASSERT(!type.isUnsizedArray());
4190 }
4191
4192 if (!checkConstructorArguments(line, arguments, type))
4193 {
4194 return CreateZeroNode(type);
4195 }
4196
4197 TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, &arguments);
4198 constructorNode->setLine(line);
4199
4200 return constructorNode->fold(mDiagnostics);
4201 }
4202
4203 //
4204 // Interface/uniform blocks
addInterfaceBlock(const TTypeQualifierBuilder & typeQualifierBuilder,const TSourceLoc & nameLine,const ImmutableString & blockName,TFieldList * fieldList,const ImmutableString & instanceName,const TSourceLoc & instanceLine,const TVector<unsigned int> * arraySizes,const TSourceLoc & arraySizesLine)4205 TIntermDeclaration *TParseContext::addInterfaceBlock(
4206 const TTypeQualifierBuilder &typeQualifierBuilder,
4207 const TSourceLoc &nameLine,
4208 const ImmutableString &blockName,
4209 TFieldList *fieldList,
4210 const ImmutableString &instanceName,
4211 const TSourceLoc &instanceLine,
4212 const TVector<unsigned int> *arraySizes,
4213 const TSourceLoc &arraySizesLine)
4214 {
4215 checkIsNotReserved(nameLine, blockName);
4216
4217 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
4218
4219 const bool isUniformOrBuffer =
4220 typeQualifier.qualifier == EvqUniform || typeQualifier.qualifier == EvqBuffer;
4221 const bool isShaderIoBlock = IsShaderIoBlock(typeQualifier.qualifier);
4222
4223 if (mShaderVersion < 310 && typeQualifier.qualifier != EvqUniform)
4224 {
4225 error(typeQualifier.line,
4226 "invalid qualifier: interface blocks must be uniform in version lower than GLSL ES "
4227 "3.10",
4228 getQualifierString(typeQualifier.qualifier));
4229 }
4230 else if (typeQualifier.qualifier == EvqPatchOut)
4231 {
4232 if ((!isExtensionEnabled(TExtension::EXT_tessellation_shader) && mShaderVersion < 320) ||
4233 mShaderType != GL_TESS_CONTROL_SHADER)
4234 {
4235 error(typeQualifier.line,
4236 "invalid qualifier: 'patch out' requires a tessellation control shader",
4237 getQualifierString(typeQualifier.qualifier));
4238 }
4239 }
4240 else if (typeQualifier.qualifier == EvqPatchIn)
4241 {
4242 if ((!isExtensionEnabled(TExtension::EXT_tessellation_shader) && mShaderVersion < 320) ||
4243 mShaderType != GL_TESS_EVALUATION_SHADER)
4244 {
4245 error(typeQualifier.line,
4246 "invalid qualifier: 'patch in' requires a tessellation evaluation shader",
4247 getQualifierString(typeQualifier.qualifier));
4248 }
4249 }
4250 else if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer)
4251 {
4252 if (isShaderIoBlock)
4253 {
4254 if (!isExtensionEnabled(TExtension::OES_shader_io_blocks) &&
4255 !isExtensionEnabled(TExtension::EXT_shader_io_blocks) &&
4256 !isExtensionEnabled(TExtension::OES_geometry_shader) &&
4257 !isExtensionEnabled(TExtension::EXT_geometry_shader) && mShaderVersion < 320)
4258 {
4259 error(typeQualifier.line,
4260 "invalid qualifier: shader IO blocks need shader io block extension",
4261 getQualifierString(typeQualifier.qualifier));
4262 }
4263
4264 if (mShaderType == GL_TESS_CONTROL_SHADER && arraySizes == nullptr)
4265 {
4266 error(typeQualifier.line, "type must be an array", blockName);
4267 }
4268 }
4269 else
4270 {
4271 error(typeQualifier.line,
4272 "invalid qualifier: interface blocks must be uniform or buffer",
4273 getQualifierString(typeQualifier.qualifier));
4274 }
4275 }
4276
4277 if (typeQualifier.invariant)
4278 {
4279 error(typeQualifier.line, "invalid qualifier on interface block", "invariant");
4280 }
4281
4282 if (typeQualifier.qualifier != EvqBuffer)
4283 {
4284 checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
4285 }
4286
4287 // Verify array sizes
4288 if (arraySizes)
4289 {
4290 if (isUniformOrBuffer)
4291 {
4292 if (arraySizes->size() == 0)
4293 {
4294 error(arraySizesLine, "unsized arrays are not allowed with interface blocks", "");
4295 }
4296 if (arraySizes->size() > 1)
4297 {
4298 error(arraySizesLine, "array of arrays are not allowed with interface blocks", "");
4299 }
4300 }
4301 else if (isShaderIoBlock)
4302 {
4303 size_t arrayDimensions = arraySizes->size();
4304
4305 // Geometry shader inputs have a level arrayness that must be ignored.
4306 if (mShaderType == GL_GEOMETRY_SHADER_EXT && IsVaryingIn(typeQualifier.qualifier))
4307 {
4308 ASSERT(arrayDimensions > 0);
4309 --arrayDimensions;
4310
4311 // Validate that the array size of input matches the geometry layout
4312 // declaration, if not automatic (specified as []).
4313 const unsigned int geometryDim = arraySizes->back();
4314 if (geometryDim > 0 && geometryDim != mGeometryInputArraySize)
4315 {
4316 error(arraySizesLine,
4317 "geometry shader input block array size inconsistent "
4318 "with primitive",
4319 "");
4320 }
4321 }
4322
4323 if (arrayDimensions > 1)
4324 {
4325 error(arraySizesLine, "array of arrays are not allowed with I/O blocks", "");
4326 }
4327 }
4328 }
4329 else if (isShaderIoBlock && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4330 IsVaryingIn(typeQualifier.qualifier))
4331 {
4332 error(arraySizesLine, "geometry shader input blocks must be an array", "");
4333 }
4334
4335 checkIndexIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.index);
4336
4337 if (mShaderVersion < 310)
4338 {
4339 checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
4340 }
4341 else
4342 {
4343 unsigned int arraySize =
4344 arraySizes == nullptr || arraySizes->empty() ? 0 : (*arraySizes)[0];
4345 checkBlockBindingIsValid(typeQualifier.line, typeQualifier.qualifier,
4346 typeQualifier.layoutQualifier.binding, arraySize);
4347 }
4348
4349 checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
4350 checkEarlyFragmentTestsIsNotSpecified(typeQualifier.line,
4351 typeQualifier.layoutQualifier.earlyFragmentTests);
4352 checkNoncoherentIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.noncoherent);
4353
4354 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
4355 if (!IsShaderIoBlock(typeQualifier.qualifier) && typeQualifier.qualifier != EvqPatchIn &&
4356 typeQualifier.qualifier != EvqPatchOut)
4357 {
4358 checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
4359 }
4360 checkStd430IsForShaderStorageBlock(typeQualifier.line, blockLayoutQualifier.blockStorage,
4361 typeQualifier.qualifier);
4362
4363 if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
4364 {
4365 if (typeQualifier.qualifier == EvqUniform)
4366 {
4367 blockLayoutQualifier.matrixPacking = mDefaultUniformMatrixPacking;
4368 }
4369 else if (typeQualifier.qualifier == EvqBuffer)
4370 {
4371 blockLayoutQualifier.matrixPacking = mDefaultBufferMatrixPacking;
4372 }
4373 }
4374
4375 if (blockLayoutQualifier.blockStorage == EbsUnspecified)
4376 {
4377 if (typeQualifier.qualifier == EvqUniform)
4378 {
4379 blockLayoutQualifier.blockStorage = mDefaultUniformBlockStorage;
4380 }
4381 else if (typeQualifier.qualifier == EvqBuffer)
4382 {
4383 blockLayoutQualifier.blockStorage = mDefaultBufferBlockStorage;
4384 }
4385 }
4386
4387 checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
4388
4389 checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
4390
4391 // check for sampler types and apply layout qualifiers
4392 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
4393 {
4394 TField *field = (*fieldList)[memberIndex];
4395 TType *fieldType = field->type();
4396 if (IsOpaqueType(fieldType->getBasicType()))
4397 {
4398 std::string reason("unsupported type - ");
4399 reason += fieldType->getBasicString();
4400 reason += " types are not allowed in interface blocks";
4401 error(field->line(), reason.c_str(), fieldType->getBasicString());
4402 }
4403
4404 const TQualifier qualifier = fieldType->getQualifier();
4405 switch (qualifier)
4406 {
4407 case EvqGlobal:
4408 break;
4409 case EvqUniform:
4410 if (typeQualifier.qualifier == EvqBuffer)
4411 {
4412 error(field->line(), "invalid qualifier on shader storage block member",
4413 getQualifierString(qualifier));
4414 }
4415 break;
4416 case EvqBuffer:
4417 if (typeQualifier.qualifier == EvqUniform)
4418 {
4419 error(field->line(), "invalid qualifier on uniform block member",
4420 getQualifierString(qualifier));
4421 }
4422 break;
4423 // a member variable in io block may have different interpolation.
4424 case EvqFlatIn:
4425 case EvqFlatOut:
4426 case EvqNoPerspectiveIn:
4427 case EvqNoPerspectiveOut:
4428 case EvqSmoothIn:
4429 case EvqSmoothOut:
4430 case EvqCentroidIn:
4431 case EvqCentroidOut:
4432 break;
4433 // a member variable can have an incomplete qualifier because shader io block has either
4434 // in or out.
4435 case EvqSmooth:
4436 case EvqFlat:
4437 case EvqNoPerspective:
4438 case EvqCentroid:
4439 case EvqGeometryIn:
4440 case EvqGeometryOut:
4441 if (!IsShaderIoBlock(typeQualifier.qualifier) &&
4442 typeQualifier.qualifier != EvqPatchIn &&
4443 typeQualifier.qualifier != EvqPatchOut &&
4444 typeQualifier.qualifier != EvqGeometryIn &&
4445 typeQualifier.qualifier != EvqGeometryOut)
4446 {
4447 error(field->line(), "invalid qualifier on interface block member",
4448 getQualifierString(qualifier));
4449 }
4450 break;
4451 default:
4452 error(field->line(), "invalid qualifier on interface block member",
4453 getQualifierString(qualifier));
4454 break;
4455 }
4456
4457 // On interface block members, invariant is only applicable to output I/O blocks.
4458 const bool isOutputShaderIoBlock = isShaderIoBlock && IsShaderOut(typeQualifier.qualifier);
4459 if (fieldType->isInvariant() && !isOutputShaderIoBlock)
4460 {
4461 error(field->line(), "invalid qualifier on interface block member", "invariant");
4462 }
4463
4464 // check layout qualifiers
4465 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
4466 checkIndexIsNotSpecified(field->line(), fieldLayoutQualifier.index);
4467 checkBindingIsNotSpecified(field->line(), fieldLayoutQualifier.binding);
4468
4469 if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
4470 {
4471 error(field->line(), "invalid layout qualifier: cannot be used here",
4472 getBlockStorageString(fieldLayoutQualifier.blockStorage));
4473 }
4474
4475 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
4476 {
4477 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
4478 }
4479 else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
4480 {
4481 warning(field->line(),
4482 "extraneous layout qualifier: only has an effect on matrix types",
4483 getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
4484 }
4485
4486 fieldType->setLayoutQualifier(fieldLayoutQualifier);
4487
4488 if (mShaderVersion < 310 || memberIndex != fieldList->size() - 1u ||
4489 typeQualifier.qualifier != EvqBuffer)
4490 {
4491 // ESSL 3.10 spec section 4.1.9 allows for runtime-sized arrays.
4492 checkIsNotUnsizedArray(field->line(),
4493 "array members of interface blocks must specify a size",
4494 field->name(), field->type());
4495 }
4496
4497 if (typeQualifier.qualifier == EvqBuffer)
4498 {
4499 // set memory qualifiers
4500 // GLSL ES 3.10 session 4.9 [Memory Access Qualifiers]. When a block declaration is
4501 // qualified with a memory qualifier, it is as if all of its members were declared with
4502 // the same memory qualifier.
4503 const TMemoryQualifier &blockMemoryQualifier = typeQualifier.memoryQualifier;
4504 TMemoryQualifier fieldMemoryQualifier = fieldType->getMemoryQualifier();
4505 fieldMemoryQualifier.readonly |= blockMemoryQualifier.readonly;
4506 fieldMemoryQualifier.writeonly |= blockMemoryQualifier.writeonly;
4507 fieldMemoryQualifier.coherent |= blockMemoryQualifier.coherent;
4508 fieldMemoryQualifier.restrictQualifier |= blockMemoryQualifier.restrictQualifier;
4509 fieldMemoryQualifier.volatileQualifier |= blockMemoryQualifier.volatileQualifier;
4510 // TODO(jiajia.qin@intel.com): Decide whether if readonly and writeonly buffer variable
4511 // is legal. See bug https://github.com/KhronosGroup/OpenGL-API/issues/7
4512 fieldType->setMemoryQualifier(fieldMemoryQualifier);
4513 }
4514 }
4515
4516 TInterfaceBlock *interfaceBlock = new TInterfaceBlock(
4517 &symbolTable, blockName, fieldList, blockLayoutQualifier, SymbolType::UserDefined);
4518 if (!symbolTable.declare(interfaceBlock))
4519 {
4520 error(nameLine, "redefinition of an interface block name", blockName);
4521 }
4522
4523 TType *interfaceBlockType =
4524 new TType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier);
4525 if (arraySizes)
4526 {
4527 interfaceBlockType->makeArrays(*arraySizes);
4528 }
4529
4530 // The instance variable gets created to refer to the interface block type from the AST
4531 // regardless of if there's an instance name. It's created as an empty symbol if there is no
4532 // instance name.
4533 TVariable *instanceVariable =
4534 new TVariable(&symbolTable, instanceName, interfaceBlockType,
4535 instanceName.empty() ? SymbolType::Empty : SymbolType::UserDefined);
4536
4537 if (instanceVariable->symbolType() == SymbolType::Empty)
4538 {
4539 // define symbols for the members of the interface block
4540 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
4541 {
4542 TField *field = (*fieldList)[memberIndex];
4543 TType *fieldType = new TType(*field->type());
4544
4545 // set parent pointer of the field variable
4546 fieldType->setInterfaceBlockField(interfaceBlock, memberIndex);
4547
4548 fieldType->setQualifier(typeQualifier.qualifier);
4549
4550 TVariable *fieldVariable =
4551 new TVariable(&symbolTable, field->name(), fieldType, SymbolType::UserDefined);
4552 if (!symbolTable.declare(fieldVariable))
4553 {
4554 error(field->line(), "redefinition of an interface block member name",
4555 field->name());
4556 }
4557 }
4558 }
4559 else
4560 {
4561 checkIsNotReserved(instanceLine, instanceName);
4562
4563 // add a symbol for this interface block
4564 if (!symbolTable.declare(instanceVariable))
4565 {
4566 error(instanceLine, "redefinition of an interface block instance name", instanceName);
4567 }
4568 }
4569
4570 TIntermSymbol *blockSymbol = new TIntermSymbol(instanceVariable);
4571 blockSymbol->setLine(typeQualifier.line);
4572 TIntermDeclaration *declaration = new TIntermDeclaration();
4573 declaration->appendDeclarator(blockSymbol);
4574 declaration->setLine(nameLine);
4575
4576 exitStructDeclaration();
4577 return declaration;
4578 }
4579
enterStructDeclaration(const TSourceLoc & line,const ImmutableString & identifier)4580 void TParseContext::enterStructDeclaration(const TSourceLoc &line,
4581 const ImmutableString &identifier)
4582 {
4583 ++mStructNestingLevel;
4584
4585 // Embedded structure definitions are not supported per GLSL ES spec.
4586 // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
4587 if (mStructNestingLevel > 1)
4588 {
4589 error(line, "Embedded struct definitions are not allowed", "struct");
4590 }
4591 }
4592
exitStructDeclaration()4593 void TParseContext::exitStructDeclaration()
4594 {
4595 --mStructNestingLevel;
4596 }
4597
checkIsBelowStructNestingLimit(const TSourceLoc & line,const TField & field)4598 void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
4599 {
4600 if (!sh::IsWebGLBasedSpec(mShaderSpec))
4601 {
4602 return;
4603 }
4604
4605 if (field.type()->getBasicType() != EbtStruct)
4606 {
4607 return;
4608 }
4609
4610 // We're already inside a structure definition at this point, so add
4611 // one to the field's struct nesting.
4612 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
4613 {
4614 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
4615 if (field.type()->getStruct()->symbolType() == SymbolType::Empty)
4616 {
4617 // This may happen in case there are nested struct definitions. While they are also
4618 // invalid GLSL, they don't cause a syntax error.
4619 reasonStream << "Struct nesting";
4620 }
4621 else
4622 {
4623 reasonStream << "Reference of struct type " << field.type()->getStruct()->name();
4624 }
4625 reasonStream << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
4626 std::string reason = reasonStream.str();
4627 error(line, reason.c_str(), field.name());
4628 return;
4629 }
4630 }
4631
4632 //
4633 // Parse an array index expression
4634 //
addIndexExpression(TIntermTyped * baseExpression,const TSourceLoc & location,TIntermTyped * indexExpression)4635 TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
4636 const TSourceLoc &location,
4637 TIntermTyped *indexExpression)
4638 {
4639 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
4640 {
4641 if (baseExpression->getAsSymbolNode())
4642 {
4643 error(location, " left of '[' is not of type array, matrix, or vector ",
4644 baseExpression->getAsSymbolNode()->getName());
4645 }
4646 else
4647 {
4648 error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
4649 }
4650
4651 return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
4652 }
4653
4654 if (baseExpression->getQualifier() == EvqPerVertexIn)
4655 {
4656 if (mGeometryShaderInputPrimitiveType == EptUndefined &&
4657 mShaderType == GL_GEOMETRY_SHADER_EXT)
4658 {
4659 error(location, "missing input primitive declaration before indexing gl_in.", "[");
4660 return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
4661 }
4662 }
4663
4664 TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
4665
4666 // ES3.2 or ES3.1's EXT_gpu_shader5 allow dynamically uniform expressions to be used as indices
4667 // of opaque types (samplers and atomic counters) as well as UBOs, but not SSBOs and images.
4668 bool allowUniformIndices =
4669 mShaderVersion >= 320 || isExtensionEnabled(TExtension::EXT_gpu_shader5);
4670
4671 // ANGLE should be able to fold any constant expressions resulting in an integer - but to be
4672 // safe we don't treat "EvqConst" that's evaluated according to the spec as being sufficient
4673 // for constness. Some interpretations of the spec have allowed constant expressions with side
4674 // effects - like array length() method on a non-constant array.
4675 if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
4676 {
4677 if (baseExpression->isInterfaceBlock())
4678 {
4679 switch (baseExpression->getQualifier())
4680 {
4681 case EvqPerVertexIn:
4682 break;
4683 case EvqUniform:
4684 if (!allowUniformIndices)
4685 {
4686 error(location,
4687 "array indexes for uniform block arrays must be constant integral "
4688 "expressions",
4689 "[");
4690 }
4691 break;
4692 case EvqBuffer:
4693 error(location,
4694 "array indexes for shader storage block arrays must be constant integral "
4695 "expressions",
4696 "[");
4697 break;
4698 default:
4699 // It's ok for shader I/O blocks to be dynamically indexed
4700 if (!IsShaderIoBlock(baseExpression->getQualifier()) &&
4701 baseExpression->getQualifier() != EvqPatchIn &&
4702 baseExpression->getQualifier() != EvqPatchOut)
4703 {
4704 // We can reach here only in error cases.
4705 ASSERT(mDiagnostics->numErrors() > 0);
4706 }
4707 break;
4708 }
4709 }
4710 else if (baseExpression->getQualifier() == EvqFragmentOut)
4711 {
4712 error(location,
4713 "array indexes for fragment outputs must be constant integral expressions", "[");
4714 }
4715 else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
4716 {
4717 error(location, "array index for gl_FragData must be constant zero", "[");
4718 }
4719 else if (baseExpression->isArray())
4720 {
4721 TBasicType elementType = baseExpression->getType().getBasicType();
4722
4723 // Note: In Section 12.30 of the ESSL 3.00 spec on p143-144:
4724 //
4725 // Indexing of arrays of samplers by constant-index-expressions is
4726 // supported in GLSL ES 1.00. A constant-index-expression is an
4727 // expression formed from constant-expressions and certain loop indices,
4728 // defined for a subset of loop constructs. Should this functionality be
4729 // included in GLSL ES 3.00?
4730 //
4731 // RESOLUTION: No. Arrays of samplers may only be indexed by constant-
4732 // integral-expressions.
4733 if (IsSampler(elementType) && !allowUniformIndices && mShaderVersion > 100)
4734 {
4735 error(location, "array index for samplers must be constant integral expressions",
4736 "[");
4737 }
4738 else if (IsImage(elementType))
4739 {
4740 error(location,
4741 "array indexes for image arrays must be constant integral expressions", "[");
4742 }
4743 }
4744 }
4745
4746 if (indexConstantUnion)
4747 {
4748 // If an out-of-range index is not qualified as constant, the behavior in the spec is
4749 // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
4750 // constant fold expressions that are not constant expressions). The most compatible way to
4751 // handle this case is to report a warning instead of an error and force the index to be in
4752 // the correct range.
4753 bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
4754 int index = 0;
4755 if (indexConstantUnion->getBasicType() == EbtInt)
4756 {
4757 index = indexConstantUnion->getIConst(0);
4758 }
4759 else if (indexConstantUnion->getBasicType() == EbtUInt)
4760 {
4761 index = static_cast<int>(indexConstantUnion->getUConst(0));
4762 }
4763
4764 int safeIndex = -1;
4765
4766 if (index < 0)
4767 {
4768 outOfRangeError(outOfRangeIndexIsError, location, "index expression is negative", "[]");
4769 safeIndex = 0;
4770 }
4771
4772 if (!baseExpression->getType().isUnsizedArray())
4773 {
4774 if (baseExpression->isArray())
4775 {
4776 if (baseExpression->getQualifier() == EvqFragData && index > 0)
4777 {
4778 if (!isExtensionEnabled(TExtension::EXT_draw_buffers))
4779 {
4780 outOfRangeError(outOfRangeIndexIsError, location,
4781 "array index for gl_FragData must be zero when "
4782 "GL_EXT_draw_buffers is disabled",
4783 "[]");
4784 safeIndex = 0;
4785 }
4786 }
4787 }
4788 // Only do generic out-of-range check if similar error hasn't already been reported.
4789 if (safeIndex < 0)
4790 {
4791 if (baseExpression->isArray())
4792 {
4793 safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
4794 baseExpression->getOutermostArraySize(),
4795 "array index out of range");
4796 }
4797 else if (baseExpression->isMatrix())
4798 {
4799 safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
4800 baseExpression->getType().getCols(),
4801 "matrix field selection out of range");
4802 }
4803 else
4804 {
4805 ASSERT(baseExpression->isVector());
4806 safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
4807 baseExpression->getType().getNominalSize(),
4808 "vector field selection out of range");
4809 }
4810 }
4811
4812 ASSERT(safeIndex >= 0);
4813 // Data of constant unions can't be changed, because it may be shared with other
4814 // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
4815 // sanitized object.
4816 if (safeIndex != index || indexConstantUnion->getBasicType() != EbtInt)
4817 {
4818 TConstantUnion *safeConstantUnion = new TConstantUnion();
4819 safeConstantUnion->setIConst(safeIndex);
4820 indexExpression = new TIntermConstantUnion(
4821 safeConstantUnion, TType(EbtInt, indexExpression->getPrecision(),
4822 indexExpression->getQualifier()));
4823 }
4824
4825 TIntermBinary *node =
4826 new TIntermBinary(EOpIndexDirect, baseExpression, indexExpression);
4827 node->setLine(location);
4828 return expressionOrFoldedResult(node);
4829 }
4830 }
4831
4832 markStaticReadIfSymbol(indexExpression);
4833 TIntermBinary *node = new TIntermBinary(EOpIndexIndirect, baseExpression, indexExpression);
4834 node->setLine(location);
4835 // Indirect indexing can never be constant folded.
4836 return node;
4837 }
4838
checkIndexLessThan(bool outOfRangeIndexIsError,const TSourceLoc & location,int index,int arraySize,const char * reason)4839 int TParseContext::checkIndexLessThan(bool outOfRangeIndexIsError,
4840 const TSourceLoc &location,
4841 int index,
4842 int arraySize,
4843 const char *reason)
4844 {
4845 // Should not reach here with an unsized / runtime-sized array.
4846 ASSERT(arraySize > 0);
4847 // A negative index should already have been checked.
4848 ASSERT(index >= 0);
4849 if (index >= arraySize)
4850 {
4851 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
4852 reasonStream << reason << " '" << index << "'";
4853 std::string token = reasonStream.str();
4854 outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
4855 return arraySize - 1;
4856 }
4857 return index;
4858 }
4859
addFieldSelectionExpression(TIntermTyped * baseExpression,const TSourceLoc & dotLocation,const ImmutableString & fieldString,const TSourceLoc & fieldLocation)4860 TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
4861 const TSourceLoc &dotLocation,
4862 const ImmutableString &fieldString,
4863 const TSourceLoc &fieldLocation)
4864 {
4865 if (baseExpression->isArray())
4866 {
4867 error(fieldLocation, "cannot apply dot operator to an array", ".");
4868 return baseExpression;
4869 }
4870
4871 if (baseExpression->isVector())
4872 {
4873 TVector<int> fieldOffsets;
4874 if (!parseVectorFields(fieldLocation, fieldString, baseExpression->getNominalSize(),
4875 &fieldOffsets))
4876 {
4877 fieldOffsets.resize(1);
4878 fieldOffsets[0] = 0;
4879 }
4880 TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldOffsets);
4881 node->setLine(dotLocation);
4882
4883 return node->fold(mDiagnostics);
4884 }
4885 else if (baseExpression->getBasicType() == EbtStruct)
4886 {
4887 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
4888 if (fields.empty())
4889 {
4890 error(dotLocation, "structure has no fields", "Internal Error");
4891 return baseExpression;
4892 }
4893 else
4894 {
4895 bool fieldFound = false;
4896 unsigned int i;
4897 for (i = 0; i < fields.size(); ++i)
4898 {
4899 if (fields[i]->name() == fieldString)
4900 {
4901 fieldFound = true;
4902 break;
4903 }
4904 }
4905 if (fieldFound)
4906 {
4907 TIntermTyped *index = CreateIndexNode(i);
4908 index->setLine(fieldLocation);
4909 TIntermBinary *node =
4910 new TIntermBinary(EOpIndexDirectStruct, baseExpression, index);
4911 node->setLine(dotLocation);
4912 return expressionOrFoldedResult(node);
4913 }
4914 else
4915 {
4916 error(dotLocation, " no such field in structure", fieldString);
4917 return baseExpression;
4918 }
4919 }
4920 }
4921 else if (baseExpression->isInterfaceBlock())
4922 {
4923 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
4924 if (fields.empty())
4925 {
4926 error(dotLocation, "interface block has no fields", "Internal Error");
4927 return baseExpression;
4928 }
4929 else
4930 {
4931 bool fieldFound = false;
4932 unsigned int i;
4933 for (i = 0; i < fields.size(); ++i)
4934 {
4935 if (fields[i]->name() == fieldString)
4936 {
4937 fieldFound = true;
4938 break;
4939 }
4940 }
4941 if (fieldFound)
4942 {
4943 TIntermTyped *index = CreateIndexNode(i);
4944 index->setLine(fieldLocation);
4945 TIntermBinary *node =
4946 new TIntermBinary(EOpIndexDirectInterfaceBlock, baseExpression, index);
4947 node->setLine(dotLocation);
4948 // Indexing interface blocks can never be constant folded.
4949 return node;
4950 }
4951 else
4952 {
4953 error(dotLocation, " no such field in interface block", fieldString);
4954 return baseExpression;
4955 }
4956 }
4957 }
4958 else
4959 {
4960 if (mShaderVersion < 300)
4961 {
4962 error(dotLocation, " field selection requires structure or vector on left hand side",
4963 fieldString);
4964 }
4965 else
4966 {
4967 error(dotLocation,
4968 " field selection requires structure, vector, or interface block on left hand "
4969 "side",
4970 fieldString);
4971 }
4972 return baseExpression;
4973 }
4974 }
4975
parseLayoutQualifier(const ImmutableString & qualifierType,const TSourceLoc & qualifierTypeLine)4976 TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qualifierType,
4977 const TSourceLoc &qualifierTypeLine)
4978 {
4979 TLayoutQualifier qualifier = TLayoutQualifier::Create();
4980
4981 if (qualifierType == "shared")
4982 {
4983 if (sh::IsWebGLBasedSpec(mShaderSpec))
4984 {
4985 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
4986 }
4987 qualifier.blockStorage = EbsShared;
4988 }
4989 else if (qualifierType == "packed")
4990 {
4991 if (sh::IsWebGLBasedSpec(mShaderSpec))
4992 {
4993 error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
4994 }
4995 qualifier.blockStorage = EbsPacked;
4996 }
4997 else if (qualifierType == "std430")
4998 {
4999 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5000 qualifier.blockStorage = EbsStd430;
5001 }
5002 else if (qualifierType == "std140")
5003 {
5004 qualifier.blockStorage = EbsStd140;
5005 }
5006 else if (qualifierType == "row_major")
5007 {
5008 qualifier.matrixPacking = EmpRowMajor;
5009 }
5010 else if (qualifierType == "column_major")
5011 {
5012 qualifier.matrixPacking = EmpColumnMajor;
5013 }
5014 else if (qualifierType == "location")
5015 {
5016 error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
5017 qualifierType);
5018 }
5019 else if (qualifierType == "yuv" && mShaderType == GL_FRAGMENT_SHADER)
5020 {
5021 if (checkCanUseExtension(qualifierTypeLine, TExtension::EXT_YUV_target))
5022 {
5023 qualifier.yuv = true;
5024 }
5025 }
5026 else if (qualifierType == "early_fragment_tests")
5027 {
5028 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5029 qualifier.earlyFragmentTests = true;
5030 }
5031 else if (qualifierType == "rgba32f")
5032 {
5033 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5034 qualifier.imageInternalFormat = EiifRGBA32F;
5035 }
5036 else if (qualifierType == "rgba16f")
5037 {
5038 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5039 qualifier.imageInternalFormat = EiifRGBA16F;
5040 }
5041 else if (qualifierType == "r32f")
5042 {
5043 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5044 qualifier.imageInternalFormat = EiifR32F;
5045 }
5046 else if (qualifierType == "rgba8")
5047 {
5048 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5049 qualifier.imageInternalFormat = EiifRGBA8;
5050 }
5051 else if (qualifierType == "rgba8_snorm")
5052 {
5053 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5054 qualifier.imageInternalFormat = EiifRGBA8_SNORM;
5055 }
5056 else if (qualifierType == "rgba32i")
5057 {
5058 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5059 qualifier.imageInternalFormat = EiifRGBA32I;
5060 }
5061 else if (qualifierType == "rgba16i")
5062 {
5063 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5064 qualifier.imageInternalFormat = EiifRGBA16I;
5065 }
5066 else if (qualifierType == "rgba8i")
5067 {
5068 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5069 qualifier.imageInternalFormat = EiifRGBA8I;
5070 }
5071 else if (qualifierType == "r32i")
5072 {
5073 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5074 qualifier.imageInternalFormat = EiifR32I;
5075 }
5076 else if (qualifierType == "rgba32ui")
5077 {
5078 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5079 qualifier.imageInternalFormat = EiifRGBA32UI;
5080 }
5081 else if (qualifierType == "rgba16ui")
5082 {
5083 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5084 qualifier.imageInternalFormat = EiifRGBA16UI;
5085 }
5086 else if (qualifierType == "rgba8ui")
5087 {
5088 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5089 qualifier.imageInternalFormat = EiifRGBA8UI;
5090 }
5091 else if (qualifierType == "r32ui")
5092 {
5093 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5094 qualifier.imageInternalFormat = EiifR32UI;
5095 }
5096 else if (mShaderType == GL_GEOMETRY_SHADER_EXT &&
5097 (mShaderVersion >= 320 ||
5098 (checkCanUseOneOfExtensions(
5099 qualifierTypeLine,
5100 std::array<TExtension, 2u>{
5101 {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}) &&
5102 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310))))
5103 {
5104 if (qualifierType == "points")
5105 {
5106 qualifier.primitiveType = EptPoints;
5107 }
5108 else if (qualifierType == "lines")
5109 {
5110 qualifier.primitiveType = EptLines;
5111 }
5112 else if (qualifierType == "lines_adjacency")
5113 {
5114 qualifier.primitiveType = EptLinesAdjacency;
5115 }
5116 else if (qualifierType == "triangles")
5117 {
5118 qualifier.primitiveType = EptTriangles;
5119 }
5120 else if (qualifierType == "triangles_adjacency")
5121 {
5122 qualifier.primitiveType = EptTrianglesAdjacency;
5123 }
5124 else if (qualifierType == "line_strip")
5125 {
5126 qualifier.primitiveType = EptLineStrip;
5127 }
5128 else if (qualifierType == "triangle_strip")
5129 {
5130 qualifier.primitiveType = EptTriangleStrip;
5131 }
5132 else
5133 {
5134 error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
5135 }
5136 }
5137 else if (mShaderType == GL_TESS_EVALUATION_SHADER_EXT &&
5138 (mShaderVersion >= 320 ||
5139 (checkCanUseExtension(qualifierTypeLine, TExtension::EXT_tessellation_shader) &&
5140 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310))))
5141 {
5142 if (qualifierType == "triangles")
5143 {
5144 qualifier.tesPrimitiveType = EtetTriangles;
5145 }
5146 else if (qualifierType == "quads")
5147 {
5148 qualifier.tesPrimitiveType = EtetQuads;
5149 }
5150 else if (qualifierType == "isolines")
5151 {
5152 qualifier.tesPrimitiveType = EtetIsolines;
5153 }
5154 else if (qualifierType == "equal_spacing")
5155 {
5156 qualifier.tesVertexSpacingType = EtetEqualSpacing;
5157 }
5158 else if (qualifierType == "fractional_even_spacing")
5159 {
5160 qualifier.tesVertexSpacingType = EtetFractionalEvenSpacing;
5161 }
5162 else if (qualifierType == "fractional_odd_spacing")
5163 {
5164 qualifier.tesVertexSpacingType = EtetFractionalOddSpacing;
5165 }
5166 else if (qualifierType == "cw")
5167 {
5168 qualifier.tesOrderingType = EtetCw;
5169 }
5170 else if (qualifierType == "ccw")
5171 {
5172 qualifier.tesOrderingType = EtetCcw;
5173 }
5174 else if (qualifierType == "point_mode")
5175 {
5176 qualifier.tesPointType = EtetPointMode;
5177 }
5178 else
5179 {
5180 error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
5181 }
5182 }
5183 else if (qualifierType == "noncoherent" && mShaderType == GL_FRAGMENT_SHADER)
5184 {
5185 if (checkCanUseOneOfExtensions(
5186 qualifierTypeLine, std::array<TExtension, 2u>{
5187 {TExtension::EXT_shader_framebuffer_fetch,
5188 TExtension::EXT_shader_framebuffer_fetch_non_coherent}}))
5189 {
5190 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 100);
5191 qualifier.noncoherent = true;
5192 }
5193 }
5194 else
5195 {
5196 error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
5197 }
5198
5199 return qualifier;
5200 }
5201
parseLocalSize(const ImmutableString & qualifierType,const TSourceLoc & qualifierTypeLine,int intValue,const TSourceLoc & intValueLine,const std::string & intValueString,size_t index,sh::WorkGroupSize * localSize)5202 void TParseContext::parseLocalSize(const ImmutableString &qualifierType,
5203 const TSourceLoc &qualifierTypeLine,
5204 int intValue,
5205 const TSourceLoc &intValueLine,
5206 const std::string &intValueString,
5207 size_t index,
5208 sh::WorkGroupSize *localSize)
5209 {
5210 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5211 if (intValue < 1)
5212 {
5213 std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
5214 reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
5215 std::string reason = reasonStream.str();
5216 error(intValueLine, reason.c_str(), intValueString.c_str());
5217 }
5218 (*localSize)[index] = intValue;
5219 }
5220
parseNumViews(int intValue,const TSourceLoc & intValueLine,const std::string & intValueString,int * numViews)5221 void TParseContext::parseNumViews(int intValue,
5222 const TSourceLoc &intValueLine,
5223 const std::string &intValueString,
5224 int *numViews)
5225 {
5226 // This error is only specified in WebGL, but tightens unspecified behavior in the native
5227 // specification.
5228 if (intValue < 1)
5229 {
5230 error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
5231 }
5232 *numViews = intValue;
5233 }
5234
parseInvocations(int intValue,const TSourceLoc & intValueLine,const std::string & intValueString,int * numInvocations)5235 void TParseContext::parseInvocations(int intValue,
5236 const TSourceLoc &intValueLine,
5237 const std::string &intValueString,
5238 int *numInvocations)
5239 {
5240 // Although SPEC isn't clear whether invocations can be less than 1, we add this limit because
5241 // it doesn't make sense to accept invocations <= 0.
5242 if (intValue < 1 || intValue > mMaxGeometryShaderInvocations)
5243 {
5244 error(intValueLine,
5245 "out of range: invocations must be in the range of [1, "
5246 "MAX_GEOMETRY_SHADER_INVOCATIONS_OES]",
5247 intValueString.c_str());
5248 }
5249 else
5250 {
5251 *numInvocations = intValue;
5252 }
5253 }
5254
parseMaxVertices(int intValue,const TSourceLoc & intValueLine,const std::string & intValueString,int * maxVertices)5255 void TParseContext::parseMaxVertices(int intValue,
5256 const TSourceLoc &intValueLine,
5257 const std::string &intValueString,
5258 int *maxVertices)
5259 {
5260 // Although SPEC isn't clear whether max_vertices can be less than 0, we add this limit because
5261 // it doesn't make sense to accept max_vertices < 0.
5262 if (intValue < 0 || intValue > mMaxGeometryShaderMaxVertices)
5263 {
5264 error(
5265 intValueLine,
5266 "out of range: max_vertices must be in the range of [0, gl_MaxGeometryOutputVertices]",
5267 intValueString.c_str());
5268 }
5269 else
5270 {
5271 *maxVertices = intValue;
5272 }
5273 }
5274
parseVertices(int intValue,const TSourceLoc & intValueLine,const std::string & intValueString,int * vertices)5275 void TParseContext::parseVertices(int intValue,
5276 const TSourceLoc &intValueLine,
5277 const std::string &intValueString,
5278 int *vertices)
5279 {
5280 if (intValue < 1 || intValue > mMaxPatchVertices)
5281 {
5282 error(intValueLine,
5283 "out of range : vertices must be in the range of [1, gl_MaxPatchVertices]",
5284 intValueString.c_str());
5285 }
5286 else
5287 {
5288 *vertices = intValue;
5289 }
5290 }
5291
parseIndexLayoutQualifier(int intValue,const TSourceLoc & intValueLine,const std::string & intValueString,int * index)5292 void TParseContext::parseIndexLayoutQualifier(int intValue,
5293 const TSourceLoc &intValueLine,
5294 const std::string &intValueString,
5295 int *index)
5296 {
5297 // EXT_blend_func_extended specifies that most validation should happen at link time, but since
5298 // we're validating output variable locations at compile time, it makes sense to validate that
5299 // index is 0 or 1 also at compile time. Also since we use "-1" as a placeholder for unspecified
5300 // index, we can't accept it here.
5301 if (intValue < 0 || intValue > 1)
5302 {
5303 error(intValueLine, "out of range: index layout qualifier can only be 0 or 1",
5304 intValueString.c_str());
5305 }
5306 else
5307 {
5308 *index = intValue;
5309 }
5310 }
5311
parseLayoutQualifier(const ImmutableString & qualifierType,const TSourceLoc & qualifierTypeLine,int intValue,const TSourceLoc & intValueLine)5312 TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qualifierType,
5313 const TSourceLoc &qualifierTypeLine,
5314 int intValue,
5315 const TSourceLoc &intValueLine)
5316 {
5317 TLayoutQualifier qualifier = TLayoutQualifier::Create();
5318
5319 std::string intValueString = Str(intValue);
5320
5321 if (qualifierType == "location")
5322 {
5323 // must check that location is non-negative
5324 if (intValue < 0)
5325 {
5326 error(intValueLine, "out of range: location must be non-negative",
5327 intValueString.c_str());
5328 }
5329 else
5330 {
5331 qualifier.location = intValue;
5332 qualifier.locationsSpecified = 1;
5333 }
5334 }
5335 else if (qualifierType == "binding")
5336 {
5337 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5338 if (intValue < 0)
5339 {
5340 error(intValueLine, "out of range: binding must be non-negative",
5341 intValueString.c_str());
5342 }
5343 else
5344 {
5345 qualifier.binding = intValue;
5346 }
5347 }
5348 else if (qualifierType == "offset")
5349 {
5350 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5351 if (intValue < 0)
5352 {
5353 error(intValueLine, "out of range: offset must be non-negative",
5354 intValueString.c_str());
5355 }
5356 else
5357 {
5358 qualifier.offset = intValue;
5359 }
5360 }
5361 else if (qualifierType == "local_size_x")
5362 {
5363 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
5364 &qualifier.localSize);
5365 }
5366 else if (qualifierType == "local_size_y")
5367 {
5368 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
5369 &qualifier.localSize);
5370 }
5371 else if (qualifierType == "local_size_z")
5372 {
5373 parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
5374 &qualifier.localSize);
5375 }
5376 else if (qualifierType == "num_views" && mShaderType == GL_VERTEX_SHADER)
5377 {
5378 if (checkCanUseOneOfExtensions(
5379 qualifierTypeLine, std::array<TExtension, 2u>{
5380 {TExtension::OVR_multiview, TExtension::OVR_multiview2}}))
5381 {
5382 parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
5383 }
5384 }
5385 else if (qualifierType == "invocations" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
5386 (mShaderVersion >= 320 ||
5387 checkCanUseOneOfExtensions(
5388 qualifierTypeLine,
5389 std::array<TExtension, 2u>{
5390 {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}})))
5391 {
5392 parseInvocations(intValue, intValueLine, intValueString, &qualifier.invocations);
5393 }
5394 else if (qualifierType == "max_vertices" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
5395 (mShaderVersion >= 320 ||
5396 checkCanUseOneOfExtensions(
5397 qualifierTypeLine,
5398 std::array<TExtension, 2u>{
5399 {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}})))
5400 {
5401 parseMaxVertices(intValue, intValueLine, intValueString, &qualifier.maxVertices);
5402 }
5403 else if (qualifierType == "index" && mShaderType == GL_FRAGMENT_SHADER &&
5404 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_blend_func_extended))
5405 {
5406 parseIndexLayoutQualifier(intValue, intValueLine, intValueString, &qualifier.index);
5407 }
5408 else if (qualifierType == "vertices" && mShaderType == GL_TESS_CONTROL_SHADER_EXT &&
5409 (mShaderVersion >= 320 ||
5410 checkCanUseExtension(qualifierTypeLine, TExtension::EXT_tessellation_shader)))
5411 {
5412 parseVertices(intValue, intValueLine, intValueString, &qualifier.vertices);
5413 }
5414 else
5415 {
5416 error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
5417 }
5418
5419 return qualifier;
5420 }
5421
createTypeQualifierBuilder(const TSourceLoc & loc)5422 TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
5423 {
5424 return new TTypeQualifierBuilder(
5425 new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
5426 mShaderVersion);
5427 }
5428
parseGlobalStorageQualifier(TQualifier qualifier,const TSourceLoc & loc)5429 TStorageQualifierWrapper *TParseContext::parseGlobalStorageQualifier(TQualifier qualifier,
5430 const TSourceLoc &loc)
5431 {
5432 checkIsAtGlobalLevel(loc, getQualifierString(qualifier));
5433 return new TStorageQualifierWrapper(qualifier, loc);
5434 }
5435
parseVaryingQualifier(const TSourceLoc & loc)5436 TStorageQualifierWrapper *TParseContext::parseVaryingQualifier(const TSourceLoc &loc)
5437 {
5438 if (getShaderType() == GL_VERTEX_SHADER)
5439 {
5440 return parseGlobalStorageQualifier(EvqVaryingOut, loc);
5441 }
5442 return parseGlobalStorageQualifier(EvqVaryingIn, loc);
5443 }
5444
parseInQualifier(const TSourceLoc & loc)5445 TStorageQualifierWrapper *TParseContext::parseInQualifier(const TSourceLoc &loc)
5446 {
5447 if (declaringFunction())
5448 {
5449 return new TStorageQualifierWrapper(EvqIn, loc);
5450 }
5451
5452 switch (getShaderType())
5453 {
5454 case GL_VERTEX_SHADER:
5455 {
5456 if (mShaderVersion < 300 && !anyMultiviewExtensionAvailable() &&
5457 !IsDesktopGLSpec(mShaderSpec))
5458 {
5459 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
5460 }
5461 return new TStorageQualifierWrapper(EvqVertexIn, loc);
5462 }
5463 case GL_FRAGMENT_SHADER:
5464 {
5465 if (mShaderVersion < 300 && !IsDesktopGLSpec(mShaderSpec))
5466 {
5467 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
5468 }
5469 return new TStorageQualifierWrapper(EvqFragmentIn, loc);
5470 }
5471 case GL_COMPUTE_SHADER:
5472 {
5473 return new TStorageQualifierWrapper(EvqComputeIn, loc);
5474 }
5475 case GL_GEOMETRY_SHADER:
5476 {
5477 return new TStorageQualifierWrapper(EvqGeometryIn, loc);
5478 }
5479 case GL_TESS_CONTROL_SHADER:
5480 {
5481 return new TStorageQualifierWrapper(EvqTessControlIn, loc);
5482 }
5483 case GL_TESS_EVALUATION_SHADER:
5484 {
5485 return new TStorageQualifierWrapper(EvqTessEvaluationIn, loc);
5486 }
5487 default:
5488 {
5489 UNREACHABLE();
5490 return new TStorageQualifierWrapper(EvqLast, loc);
5491 }
5492 }
5493 }
5494
parseOutQualifier(const TSourceLoc & loc)5495 TStorageQualifierWrapper *TParseContext::parseOutQualifier(const TSourceLoc &loc)
5496 {
5497 if (declaringFunction())
5498 {
5499 return new TStorageQualifierWrapper(EvqOut, loc);
5500 }
5501 switch (getShaderType())
5502 {
5503 case GL_VERTEX_SHADER:
5504 {
5505 if (mShaderVersion < 300 && !IsDesktopGLSpec(mShaderSpec))
5506 {
5507 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
5508 }
5509 return new TStorageQualifierWrapper(EvqVertexOut, loc);
5510 }
5511 case GL_FRAGMENT_SHADER:
5512 {
5513 if (mShaderVersion < 300 && !IsDesktopGLSpec(mShaderSpec))
5514 {
5515 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
5516 }
5517 return new TStorageQualifierWrapper(EvqFragmentOut, loc);
5518 }
5519 case GL_COMPUTE_SHADER:
5520 {
5521 error(loc, "storage qualifier isn't supported in compute shaders", "out");
5522 return new TStorageQualifierWrapper(EvqOut, loc);
5523 }
5524 case GL_GEOMETRY_SHADER_EXT:
5525 {
5526 return new TStorageQualifierWrapper(EvqGeometryOut, loc);
5527 }
5528 case GL_TESS_CONTROL_SHADER_EXT:
5529 {
5530 return new TStorageQualifierWrapper(EvqTessControlOut, loc);
5531 }
5532 case GL_TESS_EVALUATION_SHADER_EXT:
5533 {
5534 return new TStorageQualifierWrapper(EvqTessEvaluationOut, loc);
5535 }
5536 default:
5537 {
5538 UNREACHABLE();
5539 return new TStorageQualifierWrapper(EvqLast, loc);
5540 }
5541 }
5542 }
5543
parseInOutQualifier(const TSourceLoc & loc)5544 TStorageQualifierWrapper *TParseContext::parseInOutQualifier(const TSourceLoc &loc)
5545 {
5546 if (!declaringFunction())
5547 {
5548 if (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) ||
5549 isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent))
5550 {
5551 return new TStorageQualifierWrapper(EvqFragmentInOut, loc);
5552 }
5553
5554 error(loc,
5555 "invalid qualifier: can be used with either function parameters or the variables for "
5556 "fetching input attachment data",
5557 "inout");
5558 }
5559 return new TStorageQualifierWrapper(EvqInOut, loc);
5560 }
5561
joinLayoutQualifiers(TLayoutQualifier leftQualifier,TLayoutQualifier rightQualifier,const TSourceLoc & rightQualifierLocation)5562 TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
5563 TLayoutQualifier rightQualifier,
5564 const TSourceLoc &rightQualifierLocation)
5565 {
5566 return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
5567 mDiagnostics);
5568 }
5569
parseStructDeclarator(const ImmutableString & identifier,const TSourceLoc & loc)5570 TDeclarator *TParseContext::parseStructDeclarator(const ImmutableString &identifier,
5571 const TSourceLoc &loc)
5572 {
5573 checkIsNotReserved(loc, identifier);
5574 return new TDeclarator(identifier, loc);
5575 }
5576
parseStructArrayDeclarator(const ImmutableString & identifier,const TSourceLoc & loc,const TVector<unsigned int> * arraySizes)5577 TDeclarator *TParseContext::parseStructArrayDeclarator(const ImmutableString &identifier,
5578 const TSourceLoc &loc,
5579 const TVector<unsigned int> *arraySizes)
5580 {
5581 checkIsNotReserved(loc, identifier);
5582 return new TDeclarator(identifier, arraySizes, loc);
5583 }
5584
checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin,const TFieldList::const_iterator end,const ImmutableString & name,const TSourceLoc & location)5585 void TParseContext::checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin,
5586 const TFieldList::const_iterator end,
5587 const ImmutableString &name,
5588 const TSourceLoc &location)
5589 {
5590 for (auto fieldIter = begin; fieldIter != end; ++fieldIter)
5591 {
5592 if ((*fieldIter)->name() == name)
5593 {
5594 error(location, "duplicate field name in structure", name);
5595 }
5596 }
5597 }
5598
addStructFieldList(TFieldList * fields,const TSourceLoc & location)5599 TFieldList *TParseContext::addStructFieldList(TFieldList *fields, const TSourceLoc &location)
5600 {
5601 for (TFieldList::const_iterator fieldIter = fields->begin(); fieldIter != fields->end();
5602 ++fieldIter)
5603 {
5604 checkDoesNotHaveDuplicateFieldName(fields->begin(), fieldIter, (*fieldIter)->name(),
5605 location);
5606 }
5607 return fields;
5608 }
5609
combineStructFieldLists(TFieldList * processedFields,const TFieldList * newlyAddedFields,const TSourceLoc & location)5610 TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
5611 const TFieldList *newlyAddedFields,
5612 const TSourceLoc &location)
5613 {
5614 for (TField *field : *newlyAddedFields)
5615 {
5616 checkDoesNotHaveDuplicateFieldName(processedFields->begin(), processedFields->end(),
5617 field->name(), location);
5618 processedFields->push_back(field);
5619 }
5620 return processedFields;
5621 }
5622
addStructDeclaratorListWithQualifiers(const TTypeQualifierBuilder & typeQualifierBuilder,TPublicType * typeSpecifier,const TDeclaratorList * declaratorList)5623 TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
5624 const TTypeQualifierBuilder &typeQualifierBuilder,
5625 TPublicType *typeSpecifier,
5626 const TDeclaratorList *declaratorList)
5627 {
5628 TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
5629
5630 typeSpecifier->qualifier = typeQualifier.qualifier;
5631 typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
5632 typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
5633 typeSpecifier->invariant = typeQualifier.invariant;
5634 typeSpecifier->precise = typeQualifier.precise;
5635 if (typeQualifier.precision != EbpUndefined)
5636 {
5637 typeSpecifier->precision = typeQualifier.precision;
5638 }
5639 return addStructDeclaratorList(*typeSpecifier, declaratorList);
5640 }
5641
addStructDeclaratorList(const TPublicType & typeSpecifier,const TDeclaratorList * declaratorList)5642 TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
5643 const TDeclaratorList *declaratorList)
5644 {
5645 checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
5646 typeSpecifier.getBasicType());
5647
5648 checkIsNonVoid(typeSpecifier.getLine(), (*declaratorList)[0]->name(),
5649 typeSpecifier.getBasicType());
5650
5651 checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
5652 checkEarlyFragmentTestsIsNotSpecified(typeSpecifier.getLine(),
5653 typeSpecifier.layoutQualifier.earlyFragmentTests);
5654 checkNoncoherentIsNotSpecified(typeSpecifier.getLine(),
5655 typeSpecifier.layoutQualifier.noncoherent);
5656
5657 TFieldList *fieldList = new TFieldList();
5658
5659 for (const TDeclarator *declarator : *declaratorList)
5660 {
5661 TType *type = new TType(typeSpecifier);
5662 if (declarator->isArray())
5663 {
5664 // Don't allow arrays of arrays in ESSL < 3.10.
5665 checkArrayElementIsNotArray(typeSpecifier.getLine(), typeSpecifier);
5666 type->makeArrays(*declarator->arraySizes());
5667 }
5668
5669 TField *field =
5670 new TField(type, declarator->name(), declarator->line(), SymbolType::UserDefined);
5671 checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *field);
5672 fieldList->push_back(field);
5673 }
5674
5675 return fieldList;
5676 }
5677
addStructure(const TSourceLoc & structLine,const TSourceLoc & nameLine,const ImmutableString & structName,TFieldList * fieldList)5678 TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
5679 const TSourceLoc &nameLine,
5680 const ImmutableString &structName,
5681 TFieldList *fieldList)
5682 {
5683 SymbolType structSymbolType = SymbolType::UserDefined;
5684 if (structName.empty())
5685 {
5686 structSymbolType = SymbolType::Empty;
5687 }
5688 TStructure *structure = new TStructure(&symbolTable, structName, fieldList, structSymbolType);
5689
5690 // Store a bool in the struct if we're at global scope, to allow us to
5691 // skip the local struct scoping workaround in HLSL.
5692 structure->setAtGlobalScope(symbolTable.atGlobalLevel());
5693
5694 if (structSymbolType != SymbolType::Empty)
5695 {
5696 checkIsNotReserved(nameLine, structName);
5697 if (!symbolTable.declare(structure))
5698 {
5699 error(nameLine, "redefinition of a struct", structName);
5700 }
5701 }
5702
5703 // ensure we do not specify any storage qualifiers on the struct members
5704 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
5705 {
5706 TField &field = *(*fieldList)[typeListIndex];
5707 const TQualifier qualifier = field.type()->getQualifier();
5708 switch (qualifier)
5709 {
5710 case EvqGlobal:
5711 case EvqTemporary:
5712 break;
5713 default:
5714 error(field.line(), "invalid qualifier on struct member",
5715 getQualifierString(qualifier));
5716 break;
5717 }
5718 if (field.type()->isInvariant())
5719 {
5720 error(field.line(), "invalid qualifier on struct member", "invariant");
5721 }
5722 // ESSL 3.10 section 4.1.8 -- atomic_uint or images are not allowed as structure member.
5723 if (IsImage(field.type()->getBasicType()) || IsAtomicCounter(field.type()->getBasicType()))
5724 {
5725 error(field.line(), "disallowed type in struct", field.type()->getBasicString());
5726 }
5727
5728 checkIsNotUnsizedArray(field.line(), "array members of structs must specify a size",
5729 field.name(), field.type());
5730
5731 checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
5732
5733 checkIndexIsNotSpecified(field.line(), field.type()->getLayoutQualifier().index);
5734
5735 checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);
5736
5737 checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
5738 }
5739
5740 TTypeSpecifierNonArray typeSpecifierNonArray;
5741 typeSpecifierNonArray.initializeStruct(structure, true, structLine);
5742 exitStructDeclaration();
5743
5744 return typeSpecifierNonArray;
5745 }
5746
addSwitch(TIntermTyped * init,TIntermBlock * statementList,const TSourceLoc & loc)5747 TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
5748 TIntermBlock *statementList,
5749 const TSourceLoc &loc)
5750 {
5751 TBasicType switchType = init->getBasicType();
5752 if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
5753 init->isVector())
5754 {
5755 error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
5756 "switch");
5757 return nullptr;
5758 }
5759
5760 ASSERT(statementList);
5761 if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
5762 {
5763 ASSERT(mDiagnostics->numErrors() > 0);
5764 return nullptr;
5765 }
5766
5767 markStaticReadIfSymbol(init);
5768 TIntermSwitch *node = new TIntermSwitch(init, statementList);
5769 node->setLine(loc);
5770 return node;
5771 }
5772
addCase(TIntermTyped * condition,const TSourceLoc & loc)5773 TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
5774 {
5775 if (mSwitchNestingLevel == 0)
5776 {
5777 error(loc, "case labels need to be inside switch statements", "case");
5778 return nullptr;
5779 }
5780 if (condition == nullptr)
5781 {
5782 error(loc, "case label must have a condition", "case");
5783 return nullptr;
5784 }
5785 if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
5786 condition->isMatrix() || condition->isArray() || condition->isVector())
5787 {
5788 error(condition->getLine(), "case label must be a scalar integer", "case");
5789 }
5790 TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
5791 // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be
5792 // safe against corner cases we still check for conditionConst. Some interpretations of the
5793 // spec have allowed constant expressions with side effects - like array length() method on a
5794 // non-constant array.
5795 if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
5796 {
5797 error(condition->getLine(), "case label must be constant", "case");
5798 }
5799 TIntermCase *node = new TIntermCase(condition);
5800 node->setLine(loc);
5801 return node;
5802 }
5803
addDefault(const TSourceLoc & loc)5804 TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
5805 {
5806 if (mSwitchNestingLevel == 0)
5807 {
5808 error(loc, "default labels need to be inside switch statements", "default");
5809 return nullptr;
5810 }
5811 TIntermCase *node = new TIntermCase(nullptr);
5812 node->setLine(loc);
5813 return node;
5814 }
5815
createUnaryMath(TOperator op,TIntermTyped * child,const TSourceLoc & loc,const TFunction * func)5816 TIntermTyped *TParseContext::createUnaryMath(TOperator op,
5817 TIntermTyped *child,
5818 const TSourceLoc &loc,
5819 const TFunction *func)
5820 {
5821 ASSERT(child != nullptr);
5822
5823 switch (op)
5824 {
5825 case EOpLogicalNot:
5826 if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
5827 child->isVector())
5828 {
5829 unaryOpError(loc, GetOperatorString(op), child->getType());
5830 return nullptr;
5831 }
5832 break;
5833 case EOpBitwiseNot:
5834 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
5835 child->isMatrix() || child->isArray())
5836 {
5837 unaryOpError(loc, GetOperatorString(op), child->getType());
5838 return nullptr;
5839 }
5840 break;
5841 case EOpPostIncrement:
5842 case EOpPreIncrement:
5843 case EOpPostDecrement:
5844 case EOpPreDecrement:
5845 case EOpNegative:
5846 case EOpPositive:
5847 if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() ||
5848 child->getBasicType() == EbtBool || child->isArray() ||
5849 child->getBasicType() == EbtVoid || IsOpaqueType(child->getBasicType()))
5850 {
5851 unaryOpError(loc, GetOperatorString(op), child->getType());
5852 return nullptr;
5853 }
5854 break;
5855 // Operators for math built-ins are already type checked against their prototype.
5856 default:
5857 break;
5858 }
5859
5860 if (child->getMemoryQualifier().writeonly)
5861 {
5862 const char *opStr =
5863 BuiltInGroup::IsBuiltIn(op) ? func->name().data() : GetOperatorString(op);
5864 unaryOpError(loc, opStr, child->getType());
5865 return nullptr;
5866 }
5867
5868 markStaticReadIfSymbol(child);
5869 TIntermUnary *node = new TIntermUnary(op, child, func);
5870 node->setLine(loc);
5871
5872 return node->fold(mDiagnostics);
5873 }
5874
addUnaryMath(TOperator op,TIntermTyped * child,const TSourceLoc & loc)5875 TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
5876 {
5877 ASSERT(op != EOpNull);
5878 TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
5879 if (node == nullptr)
5880 {
5881 return child;
5882 }
5883 return node;
5884 }
5885
addUnaryMathLValue(TOperator op,TIntermTyped * child,const TSourceLoc & loc)5886 TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
5887 TIntermTyped *child,
5888 const TSourceLoc &loc)
5889 {
5890 checkCanBeLValue(loc, GetOperatorString(op), child);
5891 return addUnaryMath(op, child, loc);
5892 }
5893
expressionOrFoldedResult(TIntermTyped * expression)5894 TIntermTyped *TParseContext::expressionOrFoldedResult(TIntermTyped *expression)
5895 {
5896 // If we can, we should return the folded version of the expression for subsequent parsing. This
5897 // enables folding the containing expression during parsing as well, instead of the separate
5898 // FoldExpressions() step where folding nested expressions requires multiple full AST
5899 // traversals.
5900
5901 // Even if folding fails the fold() functions return some node representing the expression,
5902 // typically the original node. So "folded" can be assumed to be non-null.
5903 TIntermTyped *folded = expression->fold(mDiagnostics);
5904 ASSERT(folded != nullptr);
5905 if (folded->getQualifier() == expression->getQualifier())
5906 {
5907 // We need this expression to have the correct qualifier when validating the consuming
5908 // expression. So we can only return the folded node from here in case it has the same
5909 // qualifier as the original expression. In this kind of a cases the qualifier of the folded
5910 // node is EvqConst, whereas the qualifier of the expression is EvqTemporary:
5911 // 1. (true ? 1.0 : non_constant)
5912 // 2. (non_constant, 1.0)
5913 return folded;
5914 }
5915 return expression;
5916 }
5917
binaryOpCommonCheck(TOperator op,TIntermTyped * left,TIntermTyped * right,const TSourceLoc & loc)5918 bool TParseContext::binaryOpCommonCheck(TOperator op,
5919 TIntermTyped *left,
5920 TIntermTyped *right,
5921 const TSourceLoc &loc)
5922 {
5923 // Check opaque types are not allowed to be operands in expressions other than array indexing
5924 // and structure member selection.
5925 if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType()))
5926 {
5927 switch (op)
5928 {
5929 case EOpIndexDirect:
5930 case EOpIndexIndirect:
5931 break;
5932
5933 default:
5934 ASSERT(op != EOpIndexDirectStruct);
5935 error(loc, "Invalid operation for variables with an opaque type",
5936 GetOperatorString(op));
5937 return false;
5938 }
5939 }
5940
5941 if (right->getMemoryQualifier().writeonly)
5942 {
5943 error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op));
5944 return false;
5945 }
5946
5947 if (left->getMemoryQualifier().writeonly)
5948 {
5949 switch (op)
5950 {
5951 case EOpAssign:
5952 case EOpInitialize:
5953 case EOpIndexDirect:
5954 case EOpIndexIndirect:
5955 case EOpIndexDirectStruct:
5956 case EOpIndexDirectInterfaceBlock:
5957 break;
5958 default:
5959 error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op));
5960 return false;
5961 }
5962 }
5963
5964 if (left->getType().getStruct() || right->getType().getStruct())
5965 {
5966 switch (op)
5967 {
5968 case EOpIndexDirectStruct:
5969 ASSERT(left->getType().getStruct());
5970 break;
5971 case EOpEqual:
5972 case EOpNotEqual:
5973 case EOpAssign:
5974 case EOpInitialize:
5975 if (left->getType() != right->getType())
5976 {
5977 return false;
5978 }
5979 break;
5980 default:
5981 error(loc, "Invalid operation for structs", GetOperatorString(op));
5982 return false;
5983 }
5984 }
5985
5986 if (left->isInterfaceBlock() || right->isInterfaceBlock())
5987 {
5988 switch (op)
5989 {
5990 case EOpIndexDirectInterfaceBlock:
5991 ASSERT(left->getType().getInterfaceBlock());
5992 break;
5993 default:
5994 error(loc, "Invalid operation for interface blocks", GetOperatorString(op));
5995 return false;
5996 }
5997 }
5998
5999 if (left->isArray() != right->isArray())
6000 {
6001 error(loc, "array / non-array mismatch", GetOperatorString(op));
6002 return false;
6003 }
6004
6005 if (left->isArray())
6006 {
6007 ASSERT(right->isArray());
6008 if (mShaderVersion < 300)
6009 {
6010 error(loc, "Invalid operation for arrays", GetOperatorString(op));
6011 return false;
6012 }
6013
6014 switch (op)
6015 {
6016 case EOpEqual:
6017 case EOpNotEqual:
6018 case EOpAssign:
6019 case EOpInitialize:
6020 break;
6021 default:
6022 error(loc, "Invalid operation for arrays", GetOperatorString(op));
6023 return false;
6024 }
6025 // At this point, size of implicitly sized arrays should be resolved.
6026 if (left->getType().getArraySizes() != right->getType().getArraySizes())
6027 {
6028 error(loc, "array size mismatch", GetOperatorString(op));
6029 return false;
6030 }
6031 }
6032
6033 // Check ops which require integer / ivec parameters
6034 bool isBitShift = false;
6035 switch (op)
6036 {
6037 case EOpBitShiftLeft:
6038 case EOpBitShiftRight:
6039 case EOpBitShiftLeftAssign:
6040 case EOpBitShiftRightAssign:
6041 // Unsigned can be bit-shifted by signed and vice versa, but we need to
6042 // check that the basic type is an integer type.
6043 isBitShift = true;
6044 if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
6045 {
6046 return false;
6047 }
6048 break;
6049 case EOpBitwiseAnd:
6050 case EOpBitwiseXor:
6051 case EOpBitwiseOr:
6052 case EOpBitwiseAndAssign:
6053 case EOpBitwiseXorAssign:
6054 case EOpBitwiseOrAssign:
6055 // It is enough to check the type of only one operand, since later it
6056 // is checked that the operand types match.
6057 if (!IsInteger(left->getBasicType()))
6058 {
6059 return false;
6060 }
6061 break;
6062 default:
6063 break;
6064 }
6065
6066 ImplicitTypeConversion conversion = GetConversion(left->getBasicType(), right->getBasicType());
6067
6068 // Implicit type casting only supported for GL shaders
6069 if (!isBitShift && conversion != ImplicitTypeConversion::Same &&
6070 (!IsDesktopGLSpec(mShaderSpec) || !IsValidImplicitConversion(conversion, op)))
6071 {
6072 return false;
6073 }
6074
6075 // Check that:
6076 // 1. Type sizes match exactly on ops that require that.
6077 // 2. Restrictions for structs that contain arrays or samplers are respected.
6078 // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
6079 switch (op)
6080 {
6081 case EOpAssign:
6082 case EOpInitialize:
6083 case EOpEqual:
6084 case EOpNotEqual:
6085 // ESSL 1.00 sections 5.7, 5.8, 5.9
6086 if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
6087 {
6088 error(loc, "undefined operation for structs containing arrays",
6089 GetOperatorString(op));
6090 return false;
6091 }
6092 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
6093 // we interpret the spec so that this extends to structs containing samplers,
6094 // similarly to ESSL 1.00 spec.
6095 if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
6096 left->getType().isStructureContainingSamplers())
6097 {
6098 error(loc, "undefined operation for structs containing samplers",
6099 GetOperatorString(op));
6100 return false;
6101 }
6102
6103 if ((left->getNominalSize() != right->getNominalSize()) ||
6104 (left->getSecondarySize() != right->getSecondarySize()))
6105 {
6106 error(loc, "dimension mismatch", GetOperatorString(op));
6107 return false;
6108 }
6109 break;
6110 case EOpLessThan:
6111 case EOpGreaterThan:
6112 case EOpLessThanEqual:
6113 case EOpGreaterThanEqual:
6114 if (!left->isScalar() || !right->isScalar())
6115 {
6116 error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
6117 return false;
6118 }
6119 break;
6120 case EOpAdd:
6121 case EOpSub:
6122 case EOpDiv:
6123 case EOpIMod:
6124 case EOpBitShiftLeft:
6125 case EOpBitShiftRight:
6126 case EOpBitwiseAnd:
6127 case EOpBitwiseXor:
6128 case EOpBitwiseOr:
6129 case EOpAddAssign:
6130 case EOpSubAssign:
6131 case EOpDivAssign:
6132 case EOpIModAssign:
6133 case EOpBitShiftLeftAssign:
6134 case EOpBitShiftRightAssign:
6135 case EOpBitwiseAndAssign:
6136 case EOpBitwiseXorAssign:
6137 case EOpBitwiseOrAssign:
6138 if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
6139 {
6140 return false;
6141 }
6142
6143 // Are the sizes compatible?
6144 if (left->getNominalSize() != right->getNominalSize() ||
6145 left->getSecondarySize() != right->getSecondarySize())
6146 {
6147 // If the nominal sizes of operands do not match:
6148 // One of them must be a scalar.
6149 if (!left->isScalar() && !right->isScalar())
6150 return false;
6151
6152 // In the case of compound assignment other than multiply-assign,
6153 // the right side needs to be a scalar. Otherwise a vector/matrix
6154 // would be assigned to a scalar. A scalar can't be shifted by a
6155 // vector either.
6156 if (!right->isScalar() &&
6157 (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
6158 return false;
6159 }
6160 break;
6161 default:
6162 break;
6163 }
6164
6165 return true;
6166 }
6167
isMultiplicationTypeCombinationValid(TOperator op,const TType & left,const TType & right)6168 bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
6169 const TType &left,
6170 const TType &right)
6171 {
6172 switch (op)
6173 {
6174 case EOpMul:
6175 case EOpMulAssign:
6176 return left.getNominalSize() == right.getNominalSize() &&
6177 left.getSecondarySize() == right.getSecondarySize();
6178 case EOpVectorTimesScalar:
6179 return true;
6180 case EOpVectorTimesScalarAssign:
6181 ASSERT(!left.isMatrix() && !right.isMatrix());
6182 return left.isVector() && !right.isVector();
6183 case EOpVectorTimesMatrix:
6184 return left.getNominalSize() == right.getRows();
6185 case EOpVectorTimesMatrixAssign:
6186 ASSERT(!left.isMatrix() && right.isMatrix());
6187 return left.isVector() && left.getNominalSize() == right.getRows() &&
6188 left.getNominalSize() == right.getCols();
6189 case EOpMatrixTimesVector:
6190 return left.getCols() == right.getNominalSize();
6191 case EOpMatrixTimesScalar:
6192 return true;
6193 case EOpMatrixTimesScalarAssign:
6194 ASSERT(left.isMatrix() && !right.isMatrix());
6195 return !right.isVector();
6196 case EOpMatrixTimesMatrix:
6197 return left.getCols() == right.getRows();
6198 case EOpMatrixTimesMatrixAssign:
6199 ASSERT(left.isMatrix() && right.isMatrix());
6200 // We need to check two things:
6201 // 1. The matrix multiplication step is valid.
6202 // 2. The result will have the same number of columns as the lvalue.
6203 return left.getCols() == right.getRows() && left.getCols() == right.getCols();
6204
6205 default:
6206 UNREACHABLE();
6207 return false;
6208 }
6209 }
6210
addBinaryMathInternal(TOperator op,TIntermTyped * left,TIntermTyped * right,const TSourceLoc & loc)6211 TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
6212 TIntermTyped *left,
6213 TIntermTyped *right,
6214 const TSourceLoc &loc)
6215 {
6216 if (!binaryOpCommonCheck(op, left, right, loc))
6217 return nullptr;
6218
6219 switch (op)
6220 {
6221 case EOpEqual:
6222 case EOpNotEqual:
6223 case EOpLessThan:
6224 case EOpGreaterThan:
6225 case EOpLessThanEqual:
6226 case EOpGreaterThanEqual:
6227 break;
6228 case EOpLogicalOr:
6229 case EOpLogicalXor:
6230 case EOpLogicalAnd:
6231 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
6232 !right->getType().getStruct());
6233 if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
6234 {
6235 return nullptr;
6236 }
6237 // Basic types matching should have been already checked.
6238 ASSERT(right->getBasicType() == EbtBool);
6239 break;
6240 case EOpAdd:
6241 case EOpSub:
6242 case EOpDiv:
6243 case EOpMul:
6244 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
6245 !right->getType().getStruct());
6246 if (left->getBasicType() == EbtBool)
6247 {
6248 return nullptr;
6249 }
6250 break;
6251 case EOpIMod:
6252 ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
6253 !right->getType().getStruct());
6254 // Note that this is only for the % operator, not for mod()
6255 if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
6256 {
6257 return nullptr;
6258 }
6259 break;
6260 default:
6261 break;
6262 }
6263
6264 if (op == EOpMul)
6265 {
6266 op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
6267 if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
6268 {
6269 return nullptr;
6270 }
6271 }
6272
6273 TIntermBinary *node = new TIntermBinary(op, left, right);
6274 ASSERT(op != EOpAssign);
6275 markStaticReadIfSymbol(left);
6276 markStaticReadIfSymbol(right);
6277 node->setLine(loc);
6278 return expressionOrFoldedResult(node);
6279 }
6280
addBinaryMath(TOperator op,TIntermTyped * left,TIntermTyped * right,const TSourceLoc & loc)6281 TIntermTyped *TParseContext::addBinaryMath(TOperator op,
6282 TIntermTyped *left,
6283 TIntermTyped *right,
6284 const TSourceLoc &loc)
6285 {
6286 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
6287 if (node == 0)
6288 {
6289 binaryOpError(loc, GetOperatorString(op), left->getType(), right->getType());
6290 return left;
6291 }
6292 return node;
6293 }
6294
addBinaryMathBooleanResult(TOperator op,TIntermTyped * left,TIntermTyped * right,const TSourceLoc & loc)6295 TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
6296 TIntermTyped *left,
6297 TIntermTyped *right,
6298 const TSourceLoc &loc)
6299 {
6300 TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
6301 if (node == nullptr)
6302 {
6303 binaryOpError(loc, GetOperatorString(op), left->getType(), right->getType());
6304 node = CreateBoolNode(false);
6305 node->setLine(loc);
6306 }
6307 return node;
6308 }
6309
addAssign(TOperator op,TIntermTyped * left,TIntermTyped * right,const TSourceLoc & loc)6310 TIntermTyped *TParseContext::addAssign(TOperator op,
6311 TIntermTyped *left,
6312 TIntermTyped *right,
6313 const TSourceLoc &loc)
6314 {
6315 checkCanBeLValue(loc, "assign", left);
6316 TIntermBinary *node = nullptr;
6317 if (binaryOpCommonCheck(op, left, right, loc))
6318 {
6319 TIntermBinary *lValue = left->getAsBinaryNode();
6320 if ((lValue != nullptr) &&
6321 (lValue->getOp() == EOpIndexIndirect || lValue->getOp() == EOpIndexDirect) &&
6322 IsTessellationControlShaderOutput(mShaderType, lValue->getLeft()->getQualifier()))
6323 {
6324 checkTCSOutVarIndexIsValid(lValue, loc);
6325 }
6326
6327 if (op == EOpMulAssign)
6328 {
6329 op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
6330 if (isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
6331 {
6332 node = new TIntermBinary(op, left, right);
6333 }
6334 }
6335 else
6336 {
6337 node = new TIntermBinary(op, left, right);
6338 }
6339 }
6340 if (node == nullptr)
6341 {
6342 assignError(loc, "assign", left->getType(), right->getType());
6343 return left;
6344 }
6345 if (op != EOpAssign)
6346 {
6347 markStaticReadIfSymbol(left);
6348 }
6349 markStaticReadIfSymbol(right);
6350 node->setLine(loc);
6351 return node;
6352 }
6353
addComma(TIntermTyped * left,TIntermTyped * right,const TSourceLoc & loc)6354 TIntermTyped *TParseContext::addComma(TIntermTyped *left,
6355 TIntermTyped *right,
6356 const TSourceLoc &loc)
6357 {
6358 // WebGL2 section 5.26, the following results in an error:
6359 // "Sequence operator applied to void, arrays, or structs containing arrays"
6360 if (mShaderSpec == SH_WEBGL2_SPEC &&
6361 (left->isArray() || left->getBasicType() == EbtVoid ||
6362 left->getType().isStructureContainingArrays() || right->isArray() ||
6363 right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
6364 {
6365 error(loc,
6366 "sequence operator is not allowed for void, arrays, or structs containing arrays",
6367 ",");
6368 }
6369
6370 TIntermBinary *commaNode = TIntermBinary::CreateComma(left, right, mShaderVersion);
6371 markStaticReadIfSymbol(left);
6372 markStaticReadIfSymbol(right);
6373 commaNode->setLine(loc);
6374
6375 return expressionOrFoldedResult(commaNode);
6376 }
6377
addBranch(TOperator op,const TSourceLoc & loc)6378 TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
6379 {
6380 switch (op)
6381 {
6382 case EOpContinue:
6383 if (mLoopNestingLevel <= 0)
6384 {
6385 error(loc, "continue statement only allowed in loops", "");
6386 }
6387 break;
6388 case EOpBreak:
6389 if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
6390 {
6391 error(loc, "break statement only allowed in loops and switch statements", "");
6392 }
6393 break;
6394 case EOpReturn:
6395 if (mCurrentFunctionType->getBasicType() != EbtVoid)
6396 {
6397 error(loc, "non-void function must return a value", "return");
6398 }
6399 break;
6400 case EOpKill:
6401 if (mShaderType != GL_FRAGMENT_SHADER)
6402 {
6403 error(loc, "discard supported in fragment shaders only", "discard");
6404 }
6405 break;
6406 default:
6407 UNREACHABLE();
6408 break;
6409 }
6410 return addBranch(op, nullptr, loc);
6411 }
6412
addBranch(TOperator op,TIntermTyped * expression,const TSourceLoc & loc)6413 TIntermBranch *TParseContext::addBranch(TOperator op,
6414 TIntermTyped *expression,
6415 const TSourceLoc &loc)
6416 {
6417 if (expression != nullptr)
6418 {
6419 markStaticReadIfSymbol(expression);
6420 ASSERT(op == EOpReturn);
6421 mFunctionReturnsValue = true;
6422 if (mCurrentFunctionType->getBasicType() == EbtVoid)
6423 {
6424 error(loc, "void function cannot return a value", "return");
6425 }
6426 else if (*mCurrentFunctionType != expression->getType())
6427 {
6428 error(loc, "function return is not matching type:", "return");
6429 }
6430 }
6431 TIntermBranch *node = new TIntermBranch(op, expression);
6432 node->setLine(loc);
6433 return node;
6434 }
6435
appendStatement(TIntermBlock * block,TIntermNode * statement)6436 void TParseContext::appendStatement(TIntermBlock *block, TIntermNode *statement)
6437 {
6438 if (statement != nullptr)
6439 {
6440 markStaticReadIfSymbol(statement);
6441 block->appendStatement(statement);
6442 }
6443 }
6444
checkTextureGather(TIntermAggregate * functionCall)6445 void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
6446 {
6447 const TOperator op = functionCall->getOp();
6448 const TFunction *func = functionCall->getFunction();
6449 if (BuiltInGroup::IsTextureGather(op))
6450 {
6451 bool isTextureGatherOffsetOrOffsets =
6452 BuiltInGroup::IsTextureGatherOffset(op) || BuiltInGroup::IsTextureGatherOffsets(op);
6453 TIntermNode *componentNode = nullptr;
6454 TIntermSequence *arguments = functionCall->getSequence();
6455 ASSERT(arguments->size() >= 2u && arguments->size() <= 4u);
6456 const TIntermTyped *sampler = arguments->front()->getAsTyped();
6457 ASSERT(sampler != nullptr);
6458 switch (sampler->getBasicType())
6459 {
6460 case EbtSampler2D:
6461 case EbtISampler2D:
6462 case EbtUSampler2D:
6463 case EbtSampler2DArray:
6464 case EbtISampler2DArray:
6465 case EbtUSampler2DArray:
6466 if ((!isTextureGatherOffsetOrOffsets && arguments->size() == 3u) ||
6467 (isTextureGatherOffsetOrOffsets && arguments->size() == 4u))
6468 {
6469 componentNode = arguments->back();
6470 }
6471 break;
6472 case EbtSamplerCube:
6473 case EbtISamplerCube:
6474 case EbtUSamplerCube:
6475 case EbtSamplerCubeArray:
6476 case EbtISamplerCubeArray:
6477 case EbtUSamplerCubeArray:
6478 ASSERT(!isTextureGatherOffsetOrOffsets);
6479 if (arguments->size() == 3u)
6480 {
6481 componentNode = arguments->back();
6482 }
6483 break;
6484 case EbtSampler2DShadow:
6485 case EbtSampler2DArrayShadow:
6486 case EbtSamplerCubeShadow:
6487 case EbtSamplerCubeArrayShadow:
6488 break;
6489 default:
6490 UNREACHABLE();
6491 break;
6492 }
6493 if (componentNode)
6494 {
6495 const TIntermConstantUnion *componentConstantUnion =
6496 componentNode->getAsConstantUnion();
6497 if (componentNode->getAsTyped()->getQualifier() != EvqConst || !componentConstantUnion)
6498 {
6499 error(functionCall->getLine(), "Texture component must be a constant expression",
6500 func->name());
6501 }
6502 else
6503 {
6504 int component = componentConstantUnion->getIConst(0);
6505 if (component < 0 || component > 3)
6506 {
6507 error(functionCall->getLine(), "Component must be in the range [0;3]",
6508 func->name());
6509 }
6510 }
6511 }
6512 }
6513 }
6514
checkTextureOffset(TIntermAggregate * functionCall)6515 void TParseContext::checkTextureOffset(TIntermAggregate *functionCall)
6516 {
6517 const TOperator op = functionCall->getOp();
6518 const TFunction *func = functionCall->getFunction();
6519 TIntermNode *offset = nullptr;
6520 TIntermSequence *arguments = functionCall->getSequence();
6521
6522 if (BuiltInGroup::IsTextureOffsetNoBias(op) || BuiltInGroup::IsTextureGatherOffsetNoComp(op) ||
6523 BuiltInGroup::IsTextureGatherOffsetsNoComp(op))
6524 {
6525 offset = arguments->back();
6526 }
6527 else if (BuiltInGroup::IsTextureOffsetBias(op) || BuiltInGroup::IsTextureGatherOffsetComp(op) ||
6528 BuiltInGroup::IsTextureGatherOffsetsComp(op))
6529 {
6530 // A bias or comp parameter follows the offset parameter.
6531 ASSERT(arguments->size() >= 3);
6532 offset = (*arguments)[2];
6533 }
6534
6535 // If not one of the above built-ins, there's nothing to do here.
6536 if (offset == nullptr)
6537 {
6538 return;
6539 }
6540
6541 bool isTextureGatherOffset = BuiltInGroup::IsTextureGatherOffset(op);
6542 bool isTextureGatherOffsets = BuiltInGroup::IsTextureGatherOffsets(op);
6543 bool useTextureGatherOffsetConstraints = isTextureGatherOffset || isTextureGatherOffsets;
6544
6545 int minOffsetValue =
6546 useTextureGatherOffsetConstraints ? mMinProgramTextureGatherOffset : mMinProgramTexelOffset;
6547 int maxOffsetValue =
6548 useTextureGatherOffsetConstraints ? mMaxProgramTextureGatherOffset : mMaxProgramTexelOffset;
6549
6550 if (isTextureGatherOffsets)
6551 {
6552 // If textureGatherOffsets, the offsets parameter is an array, which is expected as an
6553 // aggregate constructor node.
6554 TIntermAggregate *offsetAggregate = offset->getAsAggregate();
6555 const TConstantUnion *offsetValues =
6556 offsetAggregate ? offsetAggregate->getConstantValue() : nullptr;
6557
6558 if (offsetValues == nullptr)
6559 {
6560 error(functionCall->getLine(), "Texture offsets must be a constant expression",
6561 func->name());
6562 return;
6563 }
6564
6565 constexpr unsigned int kOffsetsCount = 4;
6566 const TType &offsetAggregateType = offsetAggregate->getType();
6567 if (offsetAggregateType.getNumArraySizes() != 1 ||
6568 offsetAggregateType.getArraySizes()[0] != kOffsetsCount)
6569 {
6570 error(functionCall->getLine(), "Texture offsets must be an array of 4 elements",
6571 func->name());
6572 return;
6573 }
6574
6575 TIntermNode *firstOffset = offsetAggregate->getSequence()->front();
6576 size_t size = firstOffset->getAsTyped()->getType().getObjectSize();
6577 for (unsigned int i = 0; i < kOffsetsCount; ++i)
6578 {
6579 checkSingleTextureOffset(offset->getLine(), &offsetValues[i * size], size,
6580 minOffsetValue, maxOffsetValue);
6581 }
6582 }
6583 else
6584 {
6585 // If textureOffset or textureGatherOffset, the offset is expected to be found as a constant
6586 // union.
6587 TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
6588
6589 // ES3.2 or ES3.1's EXT_gpu_shader5 allow non-const offsets to be passed to
6590 // textureGatherOffset.
6591 bool textureGatherOffsetMustBeConst =
6592 mShaderVersion <= 310 && !isExtensionEnabled(TExtension::EXT_gpu_shader5);
6593
6594 bool isOffsetConst =
6595 offset->getAsTyped()->getQualifier() == EvqConst && offsetConstantUnion != nullptr;
6596 bool offsetMustBeConst = !isTextureGatherOffset || textureGatherOffsetMustBeConst;
6597
6598 if (!isOffsetConst && offsetMustBeConst)
6599 {
6600 error(functionCall->getLine(), "Texture offset must be a constant expression",
6601 func->name());
6602 return;
6603 }
6604
6605 // We cannot verify non-constant offsets to textureGatherOffset.
6606 if (offsetConstantUnion == nullptr)
6607 {
6608 ASSERT(!offsetMustBeConst);
6609 return;
6610 }
6611
6612 size_t size = offsetConstantUnion->getType().getObjectSize();
6613 const TConstantUnion *values = offsetConstantUnion->getConstantValue();
6614 checkSingleTextureOffset(offset->getLine(), values, size, minOffsetValue, maxOffsetValue);
6615 }
6616 }
6617
checkSingleTextureOffset(const TSourceLoc & line,const TConstantUnion * values,size_t size,int minOffsetValue,int maxOffsetValue)6618 void TParseContext::checkSingleTextureOffset(const TSourceLoc &line,
6619 const TConstantUnion *values,
6620 size_t size,
6621 int minOffsetValue,
6622 int maxOffsetValue)
6623 {
6624 for (size_t i = 0u; i < size; ++i)
6625 {
6626 ASSERT(values[i].getType() == EbtInt);
6627 int offsetValue = values[i].getIConst();
6628 if (offsetValue > maxOffsetValue || offsetValue < minOffsetValue)
6629 {
6630 std::stringstream tokenStream = sh::InitializeStream<std::stringstream>();
6631 tokenStream << offsetValue;
6632 std::string token = tokenStream.str();
6633 error(line, "Texture offset value out of valid range", token.c_str());
6634 }
6635 }
6636 }
6637
checkInterpolationFS(TIntermAggregate * functionCall)6638 void TParseContext::checkInterpolationFS(TIntermAggregate *functionCall)
6639 {
6640 const TFunction *func = functionCall->getFunction();
6641 if (!BuiltInGroup::IsInterpolationFS(functionCall->getOp()))
6642 {
6643 return;
6644 }
6645
6646 TIntermTyped *arg0 = nullptr;
6647
6648 if (functionCall->getAsAggregate())
6649 {
6650 const TIntermSequence *argp = functionCall->getSequence();
6651 if (argp->size() > 0)
6652 arg0 = (*argp)[0]->getAsTyped();
6653 }
6654 else
6655 {
6656 assert(functionCall->getAsUnaryNode());
6657 arg0 = functionCall->getAsUnaryNode()->getOperand();
6658 }
6659
6660 // Make sure the first argument is an interpolant, or an array element of an interpolant
6661 if (!IsVaryingIn(arg0->getType().getQualifier()))
6662 {
6663 // It might still be an array element.
6664 const TIntermTyped *base = FindLValueBase(arg0);
6665
6666 if (base == nullptr || (!IsVaryingIn(base->getType().getQualifier())))
6667 error(arg0->getLine(),
6668 "first argument must be an interpolant, or interpolant-array element",
6669 func->name());
6670 }
6671 }
6672
checkAtomicMemoryBuiltinFunctions(TIntermAggregate * functionCall)6673 void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall)
6674 {
6675 const TFunction *func = functionCall->getFunction();
6676 if (BuiltInGroup::IsAtomicMemory(functionCall->getOp()))
6677 {
6678 TIntermSequence *arguments = functionCall->getSequence();
6679 TIntermTyped *memNode = (*arguments)[0]->getAsTyped();
6680
6681 if (IsBufferOrSharedVariable(memNode))
6682 {
6683 return;
6684 }
6685
6686 while (memNode->getAsBinaryNode() || memNode->getAsSwizzleNode())
6687 {
6688 // Child 0 is "left" if binary, and the expression being swizzled if swizzle.
6689 // Note: we don't need to check that the binary operation is one of EOp*Index*, as any
6690 // other operation will result in a temp value which cannot be passed to this
6691 // out/inout parameter anyway.
6692 memNode = memNode->getChildNode(0)->getAsTyped();
6693 if (IsBufferOrSharedVariable(memNode))
6694 {
6695 return;
6696 }
6697 }
6698
6699 error(memNode->getLine(),
6700 "The value passed to the mem argument of an atomic memory function does not "
6701 "correspond to a buffer or shared variable.",
6702 func->name());
6703 }
6704 }
6705
6706 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate * functionCall)6707 void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
6708 {
6709 const TOperator op = functionCall->getOp();
6710
6711 if (BuiltInGroup::IsImage(op))
6712 {
6713 TIntermSequence *arguments = functionCall->getSequence();
6714 TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
6715
6716 const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
6717
6718 if (BuiltInGroup::IsImageStore(op))
6719 {
6720 if (memoryQualifier.readonly)
6721 {
6722 error(imageNode->getLine(),
6723 "'imageStore' cannot be used with images qualified as 'readonly'",
6724 GetImageArgumentToken(imageNode));
6725 }
6726 }
6727 else if (BuiltInGroup::IsImageLoad(op))
6728 {
6729 if (memoryQualifier.writeonly)
6730 {
6731 error(imageNode->getLine(),
6732 "'imageLoad' cannot be used with images qualified as 'writeonly'",
6733 GetImageArgumentToken(imageNode));
6734 }
6735 }
6736 else if (BuiltInGroup::IsImageAtomic(op))
6737 {
6738 if (memoryQualifier.readonly)
6739 {
6740 error(imageNode->getLine(),
6741 "'imageAtomic' cannot be used with images qualified as 'readonly'",
6742 GetImageArgumentToken(imageNode));
6743 }
6744 if (memoryQualifier.writeonly)
6745 {
6746 error(imageNode->getLine(),
6747 "'imageAtomic' cannot be used with images qualified as 'writeonly'",
6748 GetImageArgumentToken(imageNode));
6749 }
6750 }
6751 }
6752 }
6753
6754 // GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
checkImageMemoryAccessForUserDefinedFunctions(const TFunction * functionDefinition,const TIntermAggregate * functionCall)6755 void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
6756 const TFunction *functionDefinition,
6757 const TIntermAggregate *functionCall)
6758 {
6759 ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
6760
6761 const TIntermSequence &arguments = *functionCall->getSequence();
6762
6763 ASSERT(functionDefinition->getParamCount() == arguments.size());
6764
6765 for (size_t i = 0; i < arguments.size(); ++i)
6766 {
6767 TIntermTyped *typedArgument = arguments[i]->getAsTyped();
6768 const TType &functionArgumentType = typedArgument->getType();
6769 const TType &functionParameterType = functionDefinition->getParam(i)->getType();
6770 ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
6771
6772 if (IsImage(functionArgumentType.getBasicType()))
6773 {
6774 const TMemoryQualifier &functionArgumentMemoryQualifier =
6775 functionArgumentType.getMemoryQualifier();
6776 const TMemoryQualifier &functionParameterMemoryQualifier =
6777 functionParameterType.getMemoryQualifier();
6778 if (functionArgumentMemoryQualifier.readonly &&
6779 !functionParameterMemoryQualifier.readonly)
6780 {
6781 error(functionCall->getLine(),
6782 "Function call discards the 'readonly' qualifier from image",
6783 GetImageArgumentToken(typedArgument));
6784 }
6785
6786 if (functionArgumentMemoryQualifier.writeonly &&
6787 !functionParameterMemoryQualifier.writeonly)
6788 {
6789 error(functionCall->getLine(),
6790 "Function call discards the 'writeonly' qualifier from image",
6791 GetImageArgumentToken(typedArgument));
6792 }
6793
6794 if (functionArgumentMemoryQualifier.coherent &&
6795 !functionParameterMemoryQualifier.coherent)
6796 {
6797 error(functionCall->getLine(),
6798 "Function call discards the 'coherent' qualifier from image",
6799 GetImageArgumentToken(typedArgument));
6800 }
6801
6802 if (functionArgumentMemoryQualifier.volatileQualifier &&
6803 !functionParameterMemoryQualifier.volatileQualifier)
6804 {
6805 error(functionCall->getLine(),
6806 "Function call discards the 'volatile' qualifier from image",
6807 GetImageArgumentToken(typedArgument));
6808 }
6809 }
6810 }
6811 }
6812
addFunctionCallOrMethod(TFunctionLookup * fnCall,const TSourceLoc & loc)6813 TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunctionLookup *fnCall, const TSourceLoc &loc)
6814 {
6815 if (fnCall->thisNode() != nullptr)
6816 {
6817 return addMethod(fnCall, loc);
6818 }
6819 if (fnCall->isConstructor())
6820 {
6821 return addConstructor(fnCall, loc);
6822 }
6823 return addNonConstructorFunctionCall(fnCall, loc);
6824 }
6825
addMethod(TFunctionLookup * fnCall,const TSourceLoc & loc)6826 TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc)
6827 {
6828 TIntermTyped *thisNode = fnCall->thisNode();
6829 // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
6830 // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
6831 // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
6832 // So accessing fnCall->name() below is safe.
6833 if (fnCall->name() != "length")
6834 {
6835 error(loc, "invalid method", fnCall->name());
6836 }
6837 else if (!fnCall->arguments().empty())
6838 {
6839 error(loc, "method takes no parameters", "length");
6840 }
6841 else if (!thisNode->isArray())
6842 {
6843 error(loc, "length can only be called on arrays", "length");
6844 }
6845 else if (thisNode->getQualifier() == EvqPerVertexIn &&
6846 mGeometryShaderInputPrimitiveType == EptUndefined)
6847 {
6848 ASSERT(mShaderType == GL_GEOMETRY_SHADER_EXT);
6849 error(loc, "missing input primitive declaration before calling length on gl_in", "length");
6850 }
6851 else
6852 {
6853 TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode, nullptr);
6854 markStaticReadIfSymbol(thisNode);
6855 node->setLine(loc);
6856 return node->fold(mDiagnostics);
6857 }
6858 return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst));
6859 }
6860
addNonConstructorFunctionCall(TFunctionLookup * fnCall,const TSourceLoc & loc)6861 TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCall,
6862 const TSourceLoc &loc)
6863 {
6864 // First check whether the function has been hidden by a variable name or struct typename by
6865 // using the symbol looked up in the lexical phase. If the function is not hidden, look for one
6866 // with a matching argument list.
6867 if (fnCall->symbol() != nullptr && !fnCall->symbol()->isFunction())
6868 {
6869 error(loc, "function name expected", fnCall->name());
6870 }
6871 else
6872 {
6873 // There are no inner functions, so it's enough to look for user-defined functions in the
6874 // global scope.
6875 const TSymbol *symbol = symbolTable.findGlobal(fnCall->getMangledName());
6876
6877 if (symbol == nullptr && IsDesktopGLSpec(mShaderSpec))
6878 {
6879 // If using Desktop GL spec, need to check for implicit conversion
6880 symbol = symbolTable.findGlobalWithConversion(
6881 fnCall->getMangledNamesForImplicitConversions());
6882 }
6883
6884 if (symbol != nullptr)
6885 {
6886 // A user-defined function - could be an overloaded built-in as well.
6887 ASSERT(symbol->symbolType() == SymbolType::UserDefined);
6888 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
6889 TIntermAggregate *callNode =
6890 TIntermAggregate::CreateFunctionCall(*fnCandidate, &fnCall->arguments());
6891 callNode->setLine(loc);
6892 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
6893 functionCallRValueLValueErrorCheck(fnCandidate, callNode);
6894 return callNode;
6895 }
6896
6897 symbol = symbolTable.findBuiltIn(fnCall->getMangledName(), mShaderVersion);
6898
6899 if (symbol == nullptr && IsDesktopGLSpec(mShaderSpec))
6900 {
6901 // If using Desktop GL spec, need to check for implicit conversion
6902 symbol = symbolTable.findBuiltInWithConversion(
6903 fnCall->getMangledNamesForImplicitConversions(), mShaderVersion);
6904 }
6905
6906 if (symbol != nullptr)
6907 {
6908 // A built-in function.
6909 ASSERT(symbol->symbolType() == SymbolType::BuiltIn);
6910 const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
6911
6912 if (!fnCandidate->extensions().empty() &&
6913 fnCandidate->extensions()[0] != TExtension::UNDEFINED)
6914 {
6915 checkCanUseOneOfExtensions(loc, fnCandidate->extensions());
6916 }
6917
6918 // All function calls are mapped to a built-in operation.
6919 TOperator op = fnCandidate->getBuiltInOp();
6920 if (BuiltInGroup::IsMath(op) && fnCandidate->getParamCount() == 1)
6921 {
6922 // Treat it like a built-in unary operator.
6923 TIntermNode *unaryParamNode = fnCall->arguments().front();
6924 TIntermTyped *callNode =
6925 createUnaryMath(op, unaryParamNode->getAsTyped(), loc, fnCandidate);
6926 ASSERT(callNode != nullptr);
6927 return callNode;
6928 }
6929
6930 TIntermAggregate *callNode =
6931 TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, &fnCall->arguments());
6932 callNode->setLine(loc);
6933
6934 checkAtomicMemoryBuiltinFunctions(callNode);
6935 checkTextureOffset(callNode);
6936 checkTextureGather(callNode);
6937 checkInterpolationFS(callNode);
6938 checkImageMemoryAccessForBuiltinFunctions(callNode);
6939
6940 // Some built-in functions have out parameters too.
6941 functionCallRValueLValueErrorCheck(fnCandidate, callNode);
6942
6943 // See if we can constant fold a built-in. Note that this may be possible
6944 // even if it is not const-qualified.
6945 return callNode->fold(mDiagnostics);
6946 }
6947 else
6948 {
6949 error(loc, "no matching overloaded function found", fnCall->name());
6950 }
6951 }
6952
6953 // Error message was already written. Put on an unused node for error recovery.
6954 return CreateZeroNode(TType(EbtFloat, EbpMedium, EvqConst));
6955 }
6956
addTernarySelection(TIntermTyped * cond,TIntermTyped * trueExpression,TIntermTyped * falseExpression,const TSourceLoc & loc)6957 TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
6958 TIntermTyped *trueExpression,
6959 TIntermTyped *falseExpression,
6960 const TSourceLoc &loc)
6961 {
6962 if (!checkIsScalarBool(loc, cond))
6963 {
6964 return falseExpression;
6965 }
6966
6967 if (trueExpression->getType() != falseExpression->getType())
6968 {
6969 TInfoSinkBase reasonStream;
6970 reasonStream << "mismatching ternary operator operand types '" << trueExpression->getType()
6971 << " and '" << falseExpression->getType() << "'";
6972 error(loc, reasonStream.c_str(), "?:");
6973 return falseExpression;
6974 }
6975 if (IsOpaqueType(trueExpression->getBasicType()))
6976 {
6977 // ESSL 1.00 section 4.1.7
6978 // ESSL 3.00.6 section 4.1.7
6979 // Opaque/sampler types are not allowed in most types of expressions, including ternary.
6980 // Note that structs containing opaque types don't need to be checked as structs are
6981 // forbidden below.
6982 error(loc, "ternary operator is not allowed for opaque types", "?:");
6983 return falseExpression;
6984 }
6985
6986 if (cond->getMemoryQualifier().writeonly || trueExpression->getMemoryQualifier().writeonly ||
6987 falseExpression->getMemoryQualifier().writeonly)
6988 {
6989 error(loc, "ternary operator is not allowed for variables with writeonly", "?:");
6990 return falseExpression;
6991 }
6992
6993 // ESSL 1.00.17 sections 5.2 and 5.7:
6994 // Ternary operator is not among the operators allowed for structures/arrays.
6995 // ESSL 3.00.6 section 5.7:
6996 // Ternary operator support is optional for arrays. No certainty that it works across all
6997 // devices with struct either, so we err on the side of caution here. TODO (oetuaho@nvidia.com):
6998 // Would be nice to make the spec and implementation agree completely here.
6999 if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
7000 {
7001 error(loc, "ternary operator is not allowed for structures or arrays", "?:");
7002 return falseExpression;
7003 }
7004 if (trueExpression->getBasicType() == EbtInterfaceBlock)
7005 {
7006 error(loc, "ternary operator is not allowed for interface blocks", "?:");
7007 return falseExpression;
7008 }
7009
7010 // WebGL2 section 5.26, the following results in an error:
7011 // "Ternary operator applied to void, arrays, or structs containing arrays"
7012 if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
7013 {
7014 error(loc, "ternary operator is not allowed for void", "?:");
7015 return falseExpression;
7016 }
7017
7018 TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression);
7019 markStaticReadIfSymbol(cond);
7020 markStaticReadIfSymbol(trueExpression);
7021 markStaticReadIfSymbol(falseExpression);
7022 node->setLine(loc);
7023 return expressionOrFoldedResult(node);
7024 }
7025
7026 //
7027 // Parse an array of strings using yyparse.
7028 //
7029 // Returns 0 for success.
7030 //
PaParseStrings(size_t count,const char * const string[],const int length[],TParseContext * context)7031 int PaParseStrings(size_t count,
7032 const char *const string[],
7033 const int length[],
7034 TParseContext *context)
7035 {
7036 if ((count == 0) || (string == nullptr))
7037 return 1;
7038
7039 if (glslang_initialize(context))
7040 return 1;
7041
7042 int error = glslang_scan(count, string, length, context);
7043 if (!error)
7044 error = glslang_parse(context);
7045
7046 glslang_finalize(context);
7047
7048 return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
7049 }
7050
7051 } // namespace sh
7052