Bug Summary

File:root/firefox-clang/gfx/angle/checkout/src/compiler/translator/ParseContext.cpp
Warning:line 371, column 29
The left operand of '!=' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

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