• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 // Copyright (C) 2012-2015 LunarG, Inc.
4 // Copyright (C) 2015-2018 Google, Inc.
5 // Copyright (C) 2017, 2019 ARM Limited.
6 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
7 //
8 // All rights reserved.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions
12 // are met:
13 //
14 //    Redistributions of source code must retain the above copyright
15 //    notice, this list of conditions and the following disclaimer.
16 //
17 //    Redistributions in binary form must reproduce the above
18 //    copyright notice, this list of conditions and the following
19 //    disclaimer in the documentation and/or other materials provided
20 //    with the distribution.
21 //
22 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
23 //    contributors may be used to endorse or promote products derived
24 //    from this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 // POSSIBILITY OF SUCH DAMAGE.
38 //
39 
40 #include "ParseHelper.h"
41 #include "Scan.h"
42 
43 #include "../OSDependent/osinclude.h"
44 #include <algorithm>
45 
46 #include "preprocessor/PpContext.h"
47 
48 extern int yyparse(glslang::TParseContext*);
49 
50 namespace glslang {
51 
TParseContext(TSymbolTable & symbolTable,TIntermediate & interm,bool parsingBuiltins,int version,EProfile profile,const SpvVersion & spvVersion,EShLanguage language,TInfoSink & infoSink,bool forwardCompatible,EShMessages messages,const TString * entryPoint)52 TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins,
53                              int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
54                              TInfoSink& infoSink, bool forwardCompatible, EShMessages messages,
55                              const TString* entryPoint) :
56             TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language,
57                               infoSink, forwardCompatible, messages, entryPoint),
58             inMain(false),
59             blockName(nullptr),
60             limits(resources.limits)
61 #ifndef GLSLANG_WEB
62             ,
63             atomicUintOffsets(nullptr), anyIndexLimits(false)
64 #endif
65 {
66     // decide whether precision qualifiers should be ignored or respected
67     if (isEsProfile() || spvVersion.vulkan > 0) {
68         precisionManager.respectPrecisionQualifiers();
69         if (! parsingBuiltins && language == EShLangFragment && !isEsProfile() && spvVersion.vulkan > 0)
70             precisionManager.warnAboutDefaults();
71     }
72 
73     setPrecisionDefaults();
74 
75     globalUniformDefaults.clear();
76     globalUniformDefaults.layoutMatrix = ElmColumnMajor;
77     globalUniformDefaults.layoutPacking = spvVersion.spv != 0 ? ElpStd140 : ElpShared;
78 
79     globalBufferDefaults.clear();
80     globalBufferDefaults.layoutMatrix = ElmColumnMajor;
81     globalBufferDefaults.layoutPacking = spvVersion.spv != 0 ? ElpStd430 : ElpShared;
82 
83     // use storage buffer on SPIR-V 1.3 and up
84     if (spvVersion.spv >= EShTargetSpv_1_3)
85         intermediate.setUseStorageBuffer();
86 
87     globalInputDefaults.clear();
88     globalOutputDefaults.clear();
89 
90 #ifndef GLSLANG_WEB
91     // "Shaders in the transform
92     // feedback capturing mode have an initial global default of
93     //     layout(xfb_buffer = 0) out;"
94     if (language == EShLangVertex ||
95         language == EShLangTessControl ||
96         language == EShLangTessEvaluation ||
97         language == EShLangGeometry)
98         globalOutputDefaults.layoutXfbBuffer = 0;
99 
100     if (language == EShLangGeometry)
101         globalOutputDefaults.layoutStream = 0;
102 #endif
103 
104     if (entryPoint != nullptr && entryPoint->size() > 0 && *entryPoint != "main")
105         infoSink.info.message(EPrefixError, "Source entry point must be \"main\"");
106 }
107 
~TParseContext()108 TParseContext::~TParseContext()
109 {
110 #ifndef GLSLANG_WEB
111     delete [] atomicUintOffsets;
112 #endif
113 }
114 
115 // Set up all default precisions as needed by the current environment.
116 // Intended just as a TParseContext constructor helper.
setPrecisionDefaults()117 void TParseContext::setPrecisionDefaults()
118 {
119     // Set all precision defaults to EpqNone, which is correct for all types
120     // when not obeying precision qualifiers, and correct for types that don't
121     // have defaults (thus getting an error on use) when obeying precision
122     // qualifiers.
123 
124     for (int type = 0; type < EbtNumTypes; ++type)
125         defaultPrecision[type] = EpqNone;
126 
127     for (int type = 0; type < maxSamplerIndex; ++type)
128         defaultSamplerPrecision[type] = EpqNone;
129 
130     // replace with real precision defaults for those that have them
131     if (obeyPrecisionQualifiers()) {
132         if (isEsProfile()) {
133             // Most don't have defaults, a few default to lowp.
134             TSampler sampler;
135             sampler.set(EbtFloat, Esd2D);
136             defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow;
137             sampler.set(EbtFloat, EsdCube);
138             defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow;
139             sampler.set(EbtFloat, Esd2D);
140             sampler.setExternal(true);
141             defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow;
142         }
143 
144         // If we are parsing built-in computational variables/functions, it is meaningful to record
145         // whether the built-in has no precision qualifier, as that ambiguity
146         // is used to resolve the precision from the supplied arguments/operands instead.
147         // So, we don't actually want to replace EpqNone with a default precision for built-ins.
148         if (! parsingBuiltins) {
149             if (isEsProfile() && language == EShLangFragment) {
150                 defaultPrecision[EbtInt] = EpqMedium;
151                 defaultPrecision[EbtUint] = EpqMedium;
152             } else {
153                 defaultPrecision[EbtInt] = EpqHigh;
154                 defaultPrecision[EbtUint] = EpqHigh;
155                 defaultPrecision[EbtFloat] = EpqHigh;
156             }
157 
158             if (!isEsProfile()) {
159                 // Non-ES profile
160                 // All sampler precisions default to highp.
161                 for (int type = 0; type < maxSamplerIndex; ++type)
162                     defaultSamplerPrecision[type] = EpqHigh;
163             }
164         }
165 
166         defaultPrecision[EbtSampler] = EpqLow;
167         defaultPrecision[EbtAtomicUint] = EpqHigh;
168     }
169 }
170 
setLimits(const TBuiltInResource & r)171 void TParseContext::setLimits(const TBuiltInResource& r)
172 {
173     resources = r;
174     intermediate.setLimits(r);
175 
176 #ifndef GLSLANG_WEB
177     anyIndexLimits = ! limits.generalAttributeMatrixVectorIndexing ||
178                      ! limits.generalConstantMatrixVectorIndexing ||
179                      ! limits.generalSamplerIndexing ||
180                      ! limits.generalUniformIndexing ||
181                      ! limits.generalVariableIndexing ||
182                      ! limits.generalVaryingIndexing;
183 
184 
185     // "Each binding point tracks its own current default offset for
186     // inheritance of subsequent variables using the same binding. The initial state of compilation is that all
187     // binding points have an offset of 0."
188     atomicUintOffsets = new int[resources.maxAtomicCounterBindings];
189     for (int b = 0; b < resources.maxAtomicCounterBindings; ++b)
190         atomicUintOffsets[b] = 0;
191 #endif
192 }
193 
194 //
195 // Parse an array of strings using yyparse, going through the
196 // preprocessor to tokenize the shader strings, then through
197 // the GLSL scanner.
198 //
199 // Returns true for successful acceptance of the shader, false if any errors.
200 //
parseShaderStrings(TPpContext & ppContext,TInputScanner & input,bool versionWillBeError)201 bool TParseContext::parseShaderStrings(TPpContext& ppContext, TInputScanner& input, bool versionWillBeError)
202 {
203     currentScanner = &input;
204     ppContext.setInput(input, versionWillBeError);
205     yyparse(this);
206 
207     finish();
208 
209     return numErrors == 0;
210 }
211 
212 // This is called from bison when it has a parse (syntax) error
213 // Note though that to stop cascading errors, we set EOF, which
214 // will usually cause a syntax error, so be more accurate that
215 // compilation is terminating.
parserError(const char * s)216 void TParseContext::parserError(const char* s)
217 {
218     if (! getScanner()->atEndOfInput() || numErrors == 0)
219         error(getCurrentLoc(), "", "", s, "");
220     else
221         error(getCurrentLoc(), "compilation terminated", "", "");
222 }
223 
handlePragma(const TSourceLoc & loc,const TVector<TString> & tokens)224 void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>& tokens)
225 {
226 #ifndef GLSLANG_WEB
227     if (pragmaCallback)
228         pragmaCallback(loc.line, tokens);
229 
230     if (tokens.size() == 0)
231         return;
232 
233     if (tokens[0].compare("optimize") == 0) {
234         if (tokens.size() != 4) {
235             error(loc, "optimize pragma syntax is incorrect", "#pragma", "");
236             return;
237         }
238 
239         if (tokens[1].compare("(") != 0) {
240             error(loc, "\"(\" expected after 'optimize' keyword", "#pragma", "");
241             return;
242         }
243 
244         if (tokens[2].compare("on") == 0)
245             contextPragma.optimize = true;
246         else if (tokens[2].compare("off") == 0)
247             contextPragma.optimize = false;
248         else {
249             error(loc, "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", "");
250             return;
251         }
252 
253         if (tokens[3].compare(")") != 0) {
254             error(loc, "\")\" expected to end 'optimize' pragma", "#pragma", "");
255             return;
256         }
257     } else if (tokens[0].compare("debug") == 0) {
258         if (tokens.size() != 4) {
259             error(loc, "debug pragma syntax is incorrect", "#pragma", "");
260             return;
261         }
262 
263         if (tokens[1].compare("(") != 0) {
264             error(loc, "\"(\" expected after 'debug' keyword", "#pragma", "");
265             return;
266         }
267 
268         if (tokens[2].compare("on") == 0)
269             contextPragma.debug = true;
270         else if (tokens[2].compare("off") == 0)
271             contextPragma.debug = false;
272         else {
273             error(loc, "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", "");
274             return;
275         }
276 
277         if (tokens[3].compare(")") != 0) {
278             error(loc, "\")\" expected to end 'debug' pragma", "#pragma", "");
279             return;
280         }
281     } else if (spvVersion.spv > 0 && tokens[0].compare("use_storage_buffer") == 0) {
282         if (tokens.size() != 1)
283             error(loc, "extra tokens", "#pragma", "");
284         intermediate.setUseStorageBuffer();
285     } else if (spvVersion.spv > 0 && tokens[0].compare("use_vulkan_memory_model") == 0) {
286         if (tokens.size() != 1)
287             error(loc, "extra tokens", "#pragma", "");
288         intermediate.setUseVulkanMemoryModel();
289     } else if (spvVersion.spv > 0 && tokens[0].compare("use_variable_pointers") == 0) {
290         if (tokens.size() != 1)
291             error(loc, "extra tokens", "#pragma", "");
292         if (spvVersion.spv < glslang::EShTargetSpv_1_3)
293             error(loc, "requires SPIR-V 1.3", "#pragma use_variable_pointers", "");
294         intermediate.setUseVariablePointers();
295     } else if (tokens[0].compare("once") == 0) {
296         warn(loc, "not implemented", "#pragma once", "");
297     } else if (tokens[0].compare("glslang_binary_double_output") == 0)
298         intermediate.setBinaryDoubleOutput();
299 #endif
300 }
301 
302 //
303 // Handle seeing a variable identifier in the grammar.
304 //
handleVariable(const TSourceLoc & loc,TSymbol * symbol,const TString * string)305 TIntermTyped* TParseContext::handleVariable(const TSourceLoc& loc, TSymbol* symbol, const TString* string)
306 {
307     TIntermTyped* node = nullptr;
308 
309     // Error check for requiring specific extensions present.
310     if (symbol && symbol->getNumExtensions())
311         requireExtensions(loc, symbol->getNumExtensions(), symbol->getExtensions(), symbol->getName().c_str());
312 
313 #ifndef GLSLANG_WEB
314     if (symbol && symbol->isReadOnly()) {
315         // All shared things containing an unsized array must be copied up
316         // on first use, so that all future references will share its array structure,
317         // so that editing the implicit size will effect all nodes consuming it,
318         // and so that editing the implicit size won't change the shared one.
319         //
320         // If this is a variable or a block, check it and all it contains, but if this
321         // is a member of an anonymous block, check the whole block, as the whole block
322         // will need to be copied up if it contains an unsized array.
323         //
324         // This check is being done before the block-name check further down, so guard
325         // for that too.
326         if (!symbol->getType().isUnusableName()) {
327             if (symbol->getType().containsUnsizedArray() ||
328                 (symbol->getAsAnonMember() &&
329                  symbol->getAsAnonMember()->getAnonContainer().getType().containsUnsizedArray()))
330                 makeEditable(symbol);
331         }
332     }
333 #endif
334 
335     const TVariable* variable;
336     const TAnonMember* anon = symbol ? symbol->getAsAnonMember() : nullptr;
337     if (anon) {
338         // It was a member of an anonymous container.
339 
340         // Create a subtree for its dereference.
341         variable = anon->getAnonContainer().getAsVariable();
342         TIntermTyped* container = intermediate.addSymbol(*variable, loc);
343         TIntermTyped* constNode = intermediate.addConstantUnion(anon->getMemberNumber(), loc);
344         node = intermediate.addIndex(EOpIndexDirectStruct, container, constNode, loc);
345 
346         node->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type);
347         if (node->getType().hiddenMember())
348             error(loc, "member of nameless block was not redeclared", string->c_str(), "");
349     } else {
350         // Not a member of an anonymous container.
351 
352         // The symbol table search was done in the lexical phase.
353         // See if it was a variable.
354         variable = symbol ? symbol->getAsVariable() : nullptr;
355         if (variable) {
356             if (variable->getType().isUnusableName()) {
357                 error(loc, "cannot be used (maybe an instance name is needed)", string->c_str(), "");
358                 variable = nullptr;
359             }
360         } else {
361             if (symbol)
362                 error(loc, "variable name expected", string->c_str(), "");
363         }
364 
365         // Recovery, if it wasn't found or was not a variable.
366         if (! variable)
367             variable = new TVariable(string, TType(EbtVoid));
368 
369         if (variable->getType().getQualifier().isFrontEndConstant())
370             node = intermediate.addConstantUnion(variable->getConstArray(), variable->getType(), loc);
371         else
372             node = intermediate.addSymbol(*variable, loc);
373     }
374 
375     if (variable->getType().getQualifier().isIo())
376         intermediate.addIoAccessed(*string);
377 
378     if (variable->getType().isReference() &&
379         variable->getType().getQualifier().bufferReferenceNeedsVulkanMemoryModel()) {
380         intermediate.setUseVulkanMemoryModel();
381     }
382 
383     return node;
384 }
385 
386 //
387 // Handle seeing a base[index] dereference in the grammar.
388 //
handleBracketDereference(const TSourceLoc & loc,TIntermTyped * base,TIntermTyped * index)389 TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index)
390 {
391     int indexValue = 0;
392     if (index->getQualifier().isFrontEndConstant())
393         indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst();
394 
395     // basic type checks...
396     variableCheck(base);
397 
398     if (! base->isArray() && ! base->isMatrix() && ! base->isVector() && ! base->getType().isCoopMat() &&
399         ! base->isReference()) {
400         if (base->getAsSymbolNode())
401             error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), "");
402         else
403             error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", "");
404 
405         // Insert dummy error-recovery result
406         return intermediate.addConstantUnion(0.0, EbtFloat, loc);
407     }
408 
409     if (!base->isArray() && base->isVector()) {
410         if (base->getType().contains16BitFloat())
411             requireFloat16Arithmetic(loc, "[", "does not operate on types containing float16");
412         if (base->getType().contains16BitInt())
413             requireInt16Arithmetic(loc, "[", "does not operate on types containing (u)int16");
414         if (base->getType().contains8BitInt())
415             requireInt8Arithmetic(loc, "[", "does not operate on types containing (u)int8");
416     }
417 
418     // check for constant folding
419     if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant()) {
420         // both base and index are front-end constants
421         checkIndex(loc, base->getType(), indexValue);
422         return intermediate.foldDereference(base, indexValue, loc);
423     }
424 
425     // at least one of base and index is not a front-end constant variable...
426     TIntermTyped* result = nullptr;
427 
428 #ifndef GLSLANG_WEB
429     if (base->isReference() && ! base->isArray()) {
430         requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "buffer reference indexing");
431         result = intermediate.addBinaryMath(EOpAdd, base, index, loc);
432         result->setType(base->getType());
433         return result;
434     }
435     if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
436         handleIoResizeArrayAccess(loc, base);
437 #endif
438 
439     if (index->getQualifier().isFrontEndConstant())
440         checkIndex(loc, base->getType(), indexValue);
441 
442     if (index->getQualifier().isFrontEndConstant()) {
443 #ifndef GLSLANG_WEB
444         if (base->getType().isUnsizedArray()) {
445             base->getWritableType().updateImplicitArraySize(indexValue + 1);
446             // For 2D per-view builtin arrays, update the inner dimension size in parent type
447             if (base->getQualifier().isPerView() && base->getQualifier().builtIn != EbvNone) {
448                 TIntermBinary* binaryNode = base->getAsBinaryNode();
449                 if (binaryNode) {
450                     TType& leftType = binaryNode->getLeft()->getWritableType();
451                     TArraySizes& arraySizes = *leftType.getArraySizes();
452                     assert(arraySizes.getNumDims() == 2);
453                     arraySizes.setDimSize(1, std::max(arraySizes.getDimSize(1), indexValue + 1));
454                 }
455             }
456         } else
457 #endif
458             checkIndex(loc, base->getType(), indexValue);
459         result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
460     } else {
461 #ifndef GLSLANG_WEB
462         if (base->getType().isUnsizedArray()) {
463             // we have a variable index into an unsized array, which is okay,
464             // depending on the situation
465             if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
466                 error(loc, "", "[", "array must be sized by a redeclaration or layout qualifier before being indexed with a variable");
467             else {
468                 // it is okay for a run-time sized array
469                 checkRuntimeSizable(loc, *base);
470             }
471             base->getWritableType().setArrayVariablyIndexed();
472         }
473 #endif
474         if (base->getBasicType() == EbtBlock) {
475             if (base->getQualifier().storage == EvqBuffer)
476                 requireProfile(base->getLoc(), ~EEsProfile, "variable indexing buffer block array");
477             else if (base->getQualifier().storage == EvqUniform)
478                 profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5,
479                                 "variable indexing uniform block array");
480             else {
481                 // input/output blocks either don't exist or can't be variably indexed
482             }
483         } else if (language == EShLangFragment && base->getQualifier().isPipeOutput())
484             requireProfile(base->getLoc(), ~EEsProfile, "variable indexing fragment shader output array");
485         else if (base->getBasicType() == EbtSampler && version >= 130) {
486             const char* explanation = "variable indexing sampler array";
487             requireProfile(base->getLoc(), EEsProfile | ECoreProfile | ECompatibilityProfile, explanation);
488             profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, explanation);
489             profileRequires(base->getLoc(), ECoreProfile | ECompatibilityProfile, 400, nullptr, explanation);
490         }
491 
492         result = intermediate.addIndex(EOpIndexIndirect, base, index, loc);
493     }
494 
495     // Insert valid dereferenced result type
496     TType newType(base->getType(), 0);
497     if (base->getType().getQualifier().isConstant() && index->getQualifier().isConstant()) {
498         newType.getQualifier().storage = EvqConst;
499         // If base or index is a specialization constant, the result should also be a specialization constant.
500         if (base->getType().getQualifier().isSpecConstant() || index->getQualifier().isSpecConstant()) {
501             newType.getQualifier().makeSpecConstant();
502         }
503     } else {
504         newType.getQualifier().storage = EvqTemporary;
505         newType.getQualifier().specConstant = false;
506     }
507     result->setType(newType);
508 
509 #ifndef GLSLANG_WEB
510     inheritMemoryQualifiers(base->getQualifier(), result->getWritableType().getQualifier());
511 
512     // Propagate nonuniform
513     if (base->getQualifier().isNonUniform() || index->getQualifier().isNonUniform())
514         result->getWritableType().getQualifier().nonUniform = true;
515 
516     if (anyIndexLimits)
517         handleIndexLimits(loc, base, index);
518 #endif
519 
520     return result;
521 }
522 
523 #ifndef GLSLANG_WEB
524 
525 // for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms
handleIndexLimits(const TSourceLoc &,TIntermTyped * base,TIntermTyped * index)526 void TParseContext::handleIndexLimits(const TSourceLoc& /*loc*/, TIntermTyped* base, TIntermTyped* index)
527 {
528     if ((! limits.generalSamplerIndexing && base->getBasicType() == EbtSampler) ||
529         (! limits.generalUniformIndexing && base->getQualifier().isUniformOrBuffer() && language != EShLangVertex) ||
530         (! limits.generalAttributeMatrixVectorIndexing && base->getQualifier().isPipeInput() && language == EShLangVertex && (base->getType().isMatrix() || base->getType().isVector())) ||
531         (! limits.generalConstantMatrixVectorIndexing && base->getAsConstantUnion()) ||
532         (! limits.generalVariableIndexing && ! base->getType().getQualifier().isUniformOrBuffer() &&
533                                              ! base->getType().getQualifier().isPipeInput() &&
534                                              ! base->getType().getQualifier().isPipeOutput() &&
535                                              ! base->getType().getQualifier().isConstant()) ||
536         (! limits.generalVaryingIndexing && (base->getType().getQualifier().isPipeInput() ||
537                                                 base->getType().getQualifier().isPipeOutput()))) {
538         // it's too early to know what the inductive variables are, save it for post processing
539         needsIndexLimitationChecking.push_back(index);
540     }
541 }
542 
543 // Make a shared symbol have a non-shared version that can be edited by the current
544 // compile, such that editing its type will not change the shared version and will
545 // effect all nodes sharing it.
makeEditable(TSymbol * & symbol)546 void TParseContext::makeEditable(TSymbol*& symbol)
547 {
548     TParseContextBase::makeEditable(symbol);
549 
550     // See if it's tied to IO resizing
551     if (isIoResizeArray(symbol->getType()))
552         ioArraySymbolResizeList.push_back(symbol);
553 }
554 
555 // Return true if this is a geometry shader input array or tessellation control output array
556 // or mesh shader output array.
isIoResizeArray(const TType & type) const557 bool TParseContext::isIoResizeArray(const TType& type) const
558 {
559     return type.isArray() &&
560            ((language == EShLangGeometry    && type.getQualifier().storage == EvqVaryingIn) ||
561             (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut &&
562                 ! type.getQualifier().patch) ||
563             (language == EShLangFragment && type.getQualifier().storage == EvqVaryingIn &&
564                 type.getQualifier().pervertexNV) ||
565             (language == EShLangMeshNV && type.getQualifier().storage == EvqVaryingOut &&
566                 !type.getQualifier().perTaskNV));
567 }
568 
569 // If an array is not isIoResizeArray() but is an io array, make sure it has the right size
fixIoArraySize(const TSourceLoc & loc,TType & type)570 void TParseContext::fixIoArraySize(const TSourceLoc& loc, TType& type)
571 {
572     if (! type.isArray() || type.getQualifier().patch || symbolTable.atBuiltInLevel())
573         return;
574 
575     assert(! isIoResizeArray(type));
576 
577     if (type.getQualifier().storage != EvqVaryingIn || type.getQualifier().patch)
578         return;
579 
580     if (language == EShLangTessControl || language == EShLangTessEvaluation) {
581         if (type.getOuterArraySize() != resources.maxPatchVertices) {
582             if (type.isSizedArray())
583                 error(loc, "tessellation input array size must be gl_MaxPatchVertices or implicitly sized", "[]", "");
584             type.changeOuterArraySize(resources.maxPatchVertices);
585         }
586     }
587 }
588 
589 // Issue any errors if the non-array object is missing arrayness WRT
590 // shader I/O that has array requirements.
591 // All arrayness checking is handled in array paths, this is for
ioArrayCheck(const TSourceLoc & loc,const TType & type,const TString & identifier)592 void TParseContext::ioArrayCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
593 {
594     if (! type.isArray() && ! symbolTable.atBuiltInLevel()) {
595         if (type.getQualifier().isArrayedIo(language) && !type.getQualifier().layoutPassthrough)
596             error(loc, "type must be an array:", type.getStorageQualifierString(), identifier.c_str());
597     }
598 }
599 
600 // Handle a dereference of a geometry shader input array or tessellation control output array.
601 // See ioArraySymbolResizeList comment in ParseHelper.h.
602 //
handleIoResizeArrayAccess(const TSourceLoc &,TIntermTyped * base)603 void TParseContext::handleIoResizeArrayAccess(const TSourceLoc& /*loc*/, TIntermTyped* base)
604 {
605     TIntermSymbol* symbolNode = base->getAsSymbolNode();
606     assert(symbolNode);
607     if (! symbolNode)
608         return;
609 
610     // fix array size, if it can be fixed and needs to be fixed (will allow variable indexing)
611     if (symbolNode->getType().isUnsizedArray()) {
612         int newSize = getIoArrayImplicitSize(symbolNode->getType().getQualifier());
613         if (newSize > 0)
614             symbolNode->getWritableType().changeOuterArraySize(newSize);
615     }
616 }
617 
618 // If there has been an input primitive declaration (geometry shader) or an output
619 // number of vertices declaration(tessellation shader), make sure all input array types
620 // match it in size.  Types come either from nodes in the AST or symbols in the
621 // symbol table.
622 //
623 // Types without an array size will be given one.
624 // Types already having a size that is wrong will get an error.
625 //
checkIoArraysConsistency(const TSourceLoc & loc,bool tailOnly)626 void TParseContext::checkIoArraysConsistency(const TSourceLoc &loc, bool tailOnly)
627 {
628     int requiredSize = 0;
629     TString featureString;
630     size_t listSize = ioArraySymbolResizeList.size();
631     size_t i = 0;
632 
633     // If tailOnly = true, only check the last array symbol in the list.
634     if (tailOnly) {
635         i = listSize - 1;
636     }
637     for (bool firstIteration = true; i < listSize; ++i) {
638         TType &type = ioArraySymbolResizeList[i]->getWritableType();
639 
640         // As I/O array sizes don't change, fetch requiredSize only once,
641         // except for mesh shaders which could have different I/O array sizes based on type qualifiers.
642         if (firstIteration || (language == EShLangMeshNV)) {
643             requiredSize = getIoArrayImplicitSize(type.getQualifier(), &featureString);
644             if (requiredSize == 0)
645                 break;
646             firstIteration = false;
647         }
648 
649         checkIoArrayConsistency(loc, requiredSize, featureString.c_str(), type,
650                                 ioArraySymbolResizeList[i]->getName());
651     }
652 }
653 
getIoArrayImplicitSize(const TQualifier & qualifier,TString * featureString) const654 int TParseContext::getIoArrayImplicitSize(const TQualifier &qualifier, TString *featureString) const
655 {
656     int expectedSize = 0;
657     TString str = "unknown";
658     unsigned int maxVertices = intermediate.getVertices() != TQualifier::layoutNotSet ? intermediate.getVertices() : 0;
659 
660     if (language == EShLangGeometry) {
661         expectedSize = TQualifier::mapGeometryToSize(intermediate.getInputPrimitive());
662         str = TQualifier::getGeometryString(intermediate.getInputPrimitive());
663     }
664     else if (language == EShLangTessControl) {
665         expectedSize = maxVertices;
666         str = "vertices";
667     } else if (language == EShLangFragment) {
668         // Number of vertices for Fragment shader is always three.
669         expectedSize = 3;
670         str = "vertices";
671     } else if (language == EShLangMeshNV) {
672         unsigned int maxPrimitives =
673             intermediate.getPrimitives() != TQualifier::layoutNotSet ? intermediate.getPrimitives() : 0;
674         if (qualifier.builtIn == EbvPrimitiveIndicesNV) {
675             expectedSize = maxPrimitives * TQualifier::mapGeometryToSize(intermediate.getOutputPrimitive());
676             str = "max_primitives*";
677             str += TQualifier::getGeometryString(intermediate.getOutputPrimitive());
678         }
679         else if (qualifier.isPerPrimitive()) {
680             expectedSize = maxPrimitives;
681             str = "max_primitives";
682         }
683         else {
684             expectedSize = maxVertices;
685             str = "max_vertices";
686         }
687     }
688     if (featureString)
689         *featureString = str;
690     return expectedSize;
691 }
692 
checkIoArrayConsistency(const TSourceLoc & loc,int requiredSize,const char * feature,TType & type,const TString & name)693 void TParseContext::checkIoArrayConsistency(const TSourceLoc& loc, int requiredSize, const char* feature, TType& type, const TString& name)
694 {
695     if (type.isUnsizedArray())
696         type.changeOuterArraySize(requiredSize);
697     else if (type.getOuterArraySize() != requiredSize) {
698         if (language == EShLangGeometry)
699             error(loc, "inconsistent input primitive for array size of", feature, name.c_str());
700         else if (language == EShLangTessControl)
701             error(loc, "inconsistent output number of vertices for array size of", feature, name.c_str());
702         else if (language == EShLangFragment) {
703             if (type.getOuterArraySize() > requiredSize)
704                 error(loc, " cannot be greater than 3 for pervertexNV", feature, name.c_str());
705         }
706         else if (language == EShLangMeshNV)
707             error(loc, "inconsistent output array size of", feature, name.c_str());
708         else
709             assert(0);
710     }
711 }
712 
713 #endif // GLSLANG_WEB
714 
715 // Handle seeing a binary node with a math operation.
716 // Returns nullptr if not semantically allowed.
handleBinaryMath(const TSourceLoc & loc,const char * str,TOperator op,TIntermTyped * left,TIntermTyped * right)717 TIntermTyped* TParseContext::handleBinaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right)
718 {
719     rValueErrorCheck(loc, str, left->getAsTyped());
720     rValueErrorCheck(loc, str, right->getAsTyped());
721 
722     bool allowed = true;
723     switch (op) {
724     // TODO: Bring more source language-specific checks up from intermediate.cpp
725     // to the specific parse helpers for that source language.
726     case EOpLessThan:
727     case EOpGreaterThan:
728     case EOpLessThanEqual:
729     case EOpGreaterThanEqual:
730         if (! left->isScalar() || ! right->isScalar())
731             allowed = false;
732         break;
733     default:
734         break;
735     }
736 
737     if (((left->getType().contains16BitFloat() || right->getType().contains16BitFloat()) && !float16Arithmetic()) ||
738         ((left->getType().contains16BitInt() || right->getType().contains16BitInt()) && !int16Arithmetic()) ||
739         ((left->getType().contains8BitInt() || right->getType().contains8BitInt()) && !int8Arithmetic())) {
740         allowed = false;
741     }
742 
743     TIntermTyped* result = nullptr;
744     if (allowed)
745         result = intermediate.addBinaryMath(op, left, right, loc);
746 
747     if (result == nullptr)
748         binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString());
749 
750     return result;
751 }
752 
753 // Handle seeing a unary node with a math operation.
handleUnaryMath(const TSourceLoc & loc,const char * str,TOperator op,TIntermTyped * childNode)754 TIntermTyped* TParseContext::handleUnaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* childNode)
755 {
756     rValueErrorCheck(loc, str, childNode);
757 
758     bool allowed = true;
759     if ((childNode->getType().contains16BitFloat() && !float16Arithmetic()) ||
760         (childNode->getType().contains16BitInt() && !int16Arithmetic()) ||
761         (childNode->getType().contains8BitInt() && !int8Arithmetic())) {
762         allowed = false;
763     }
764 
765     TIntermTyped* result = nullptr;
766     if (allowed)
767         result = intermediate.addUnaryMath(op, childNode, loc);
768 
769     if (result)
770         return result;
771     else
772         unaryOpError(loc, str, childNode->getCompleteString());
773 
774     return childNode;
775 }
776 
777 //
778 // Handle seeing a base.field dereference in the grammar.
779 //
handleDotDereference(const TSourceLoc & loc,TIntermTyped * base,const TString & field)780 TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TIntermTyped* base, const TString& field)
781 {
782     variableCheck(base);
783 
784     //
785     // .length() can't be resolved until we later see the function-calling syntax.
786     // Save away the name in the AST for now.  Processing is completed in
787     // handleLengthMethod().
788     //
789     if (field == "length") {
790         if (base->isArray()) {
791             profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, ".length");
792             profileRequires(loc, EEsProfile, 300, nullptr, ".length");
793         } else if (base->isVector() || base->isMatrix()) {
794             const char* feature = ".length() on vectors and matrices";
795             requireProfile(loc, ~EEsProfile, feature);
796             profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, feature);
797         } else if (!base->getType().isCoopMat()) {
798             error(loc, "does not operate on this type:", field.c_str(), base->getType().getCompleteString().c_str());
799 
800             return base;
801         }
802 
803         return intermediate.addMethod(base, TType(EbtInt), &field, loc);
804     }
805 
806     // It's not .length() if we get to here.
807 
808     if (base->isArray()) {
809         error(loc, "cannot apply to an array:", ".", field.c_str());
810 
811         return base;
812     }
813 
814     if (base->getType().isCoopMat()) {
815         error(loc, "cannot apply to a cooperative matrix type:", ".", field.c_str());
816         return base;
817     }
818 
819     // It's neither an array nor .length() if we get here,
820     // leaving swizzles and struct/block dereferences.
821 
822     TIntermTyped* result = base;
823     if ((base->isVector() || base->isScalar()) &&
824         (base->isFloatingDomain() || base->isIntegerDomain() || base->getBasicType() == EbtBool)) {
825         if (base->isScalar()) {
826             const char* dotFeature = "scalar swizzle";
827             requireProfile(loc, ~EEsProfile, dotFeature);
828             profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature);
829         }
830 
831         TSwizzleSelectors<TVectorSelector> selectors;
832         parseSwizzleSelector(loc, field, base->getVectorSize(), selectors);
833 
834         if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitFloat())
835             requireFloat16Arithmetic(loc, ".", "can't swizzle types containing float16");
836         if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitInt())
837             requireInt16Arithmetic(loc, ".", "can't swizzle types containing (u)int16");
838         if (base->isVector() && selectors.size() != 1 && base->getType().contains8BitInt())
839             requireInt8Arithmetic(loc, ".", "can't swizzle types containing (u)int8");
840 
841         if (base->isScalar()) {
842             if (selectors.size() == 1)
843                 return result;
844             else {
845                 TType type(base->getBasicType(), EvqTemporary, selectors.size());
846                 // Swizzle operations propagate specialization-constantness
847                 if (base->getQualifier().isSpecConstant())
848                     type.getQualifier().makeSpecConstant();
849                 return addConstructor(loc, base, type);
850             }
851         }
852 
853         if (base->getType().getQualifier().isFrontEndConstant())
854             result = intermediate.foldSwizzle(base, selectors, loc);
855         else {
856             if (selectors.size() == 1) {
857                 TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc);
858                 result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
859                 result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision));
860             } else {
861                 TIntermTyped* index = intermediate.addSwizzle(selectors, loc);
862                 result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc);
863                 result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size()));
864             }
865             // Swizzle operations propagate specialization-constantness
866             if (base->getType().getQualifier().isSpecConstant())
867                 result->getWritableType().getQualifier().makeSpecConstant();
868         }
869     } else if (base->isStruct() || base->isReference()) {
870         const TTypeList* fields = base->isReference() ?
871                                   base->getType().getReferentType()->getStruct() :
872                                   base->getType().getStruct();
873         bool fieldFound = false;
874         int member;
875         for (member = 0; member < (int)fields->size(); ++member) {
876             if ((*fields)[member].type->getFieldName() == field) {
877                 fieldFound = true;
878                 break;
879             }
880         }
881         if (fieldFound) {
882             if (base->getType().getQualifier().isFrontEndConstant())
883                 result = intermediate.foldDereference(base, member, loc);
884             else {
885                 blockMemberExtensionCheck(loc, base, member, field);
886                 TIntermTyped* index = intermediate.addConstantUnion(member, loc);
887                 result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc);
888                 result->setType(*(*fields)[member].type);
889                 if ((*fields)[member].type->getQualifier().isIo())
890                     intermediate.addIoAccessed(field);
891             }
892             inheritMemoryQualifiers(base->getQualifier(), result->getWritableType().getQualifier());
893         } else
894             error(loc, "no such field in structure", field.c_str(), "");
895     } else
896         error(loc, "does not apply to this type:", field.c_str(), base->getType().getCompleteString().c_str());
897 
898     // Propagate noContraction up the dereference chain
899     if (base->getQualifier().isNoContraction())
900         result->getWritableType().getQualifier().setNoContraction();
901 
902     // Propagate nonuniform
903     if (base->getQualifier().isNonUniform())
904         result->getWritableType().getQualifier().nonUniform = true;
905 
906     return result;
907 }
908 
blockMemberExtensionCheck(const TSourceLoc & loc,const TIntermTyped * base,int member,const TString & memberName)909 void TParseContext::blockMemberExtensionCheck(const TSourceLoc& loc, const TIntermTyped* base, int member, const TString& memberName)
910 {
911     // a block that needs extension checking is either 'base', or if arrayed,
912     // one level removed to the left
913     const TIntermSymbol* baseSymbol = nullptr;
914     if (base->getAsBinaryNode() == nullptr)
915         baseSymbol = base->getAsSymbolNode();
916     else
917         baseSymbol = base->getAsBinaryNode()->getLeft()->getAsSymbolNode();
918     if (baseSymbol == nullptr)
919         return;
920     const TSymbol* symbol = symbolTable.find(baseSymbol->getName());
921     if (symbol == nullptr)
922         return;
923     const TVariable* variable = symbol->getAsVariable();
924     if (variable == nullptr)
925         return;
926     if (!variable->hasMemberExtensions())
927         return;
928 
929     // We now have a variable that is the base of a dot reference
930     // with members that need extension checking.
931     if (variable->getNumMemberExtensions(member) > 0)
932         requireExtensions(loc, variable->getNumMemberExtensions(member), variable->getMemberExtensions(member), memberName.c_str());
933 }
934 
935 //
936 // Handle seeing a function declarator in the grammar.  This is the precursor
937 // to recognizing a function prototype or function definition.
938 //
handleFunctionDeclarator(const TSourceLoc & loc,TFunction & function,bool prototype)939 TFunction* TParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFunction& function, bool prototype)
940 {
941     // ES can't declare prototypes inside functions
942     if (! symbolTable.atGlobalLevel())
943         requireProfile(loc, ~EEsProfile, "local function declaration");
944 
945     //
946     // Multiple declarations of the same function name are allowed.
947     //
948     // If this is a definition, the definition production code will check for redefinitions
949     // (we don't know at this point if it's a definition or not).
950     //
951     // Redeclarations (full signature match) are allowed.  But, return types and parameter qualifiers must also match.
952     //  - except ES 100, which only allows a single prototype
953     //
954     // ES 100 does not allow redefining, but does allow overloading of built-in functions.
955     // ES 300 does not allow redefining or overloading of built-in functions.
956     //
957     bool builtIn;
958     TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn);
959     if (symbol && symbol->getAsFunction() && builtIn)
960         requireProfile(loc, ~EEsProfile, "redefinition of built-in function");
961     const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0;
962     if (prevDec) {
963         if (prevDec->isPrototyped() && prototype)
964             profileRequires(loc, EEsProfile, 300, nullptr, "multiple prototypes for same function");
965         if (prevDec->getType() != function.getType())
966             error(loc, "overloaded functions must have the same return type", function.getName().c_str(), "");
967         for (int i = 0; i < prevDec->getParamCount(); ++i) {
968             if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage)
969                 error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1);
970 
971             if ((*prevDec)[i].type->getQualifier().precision != function[i].type->getQualifier().precision)
972                 error(loc, "overloaded functions must have the same parameter precision qualifiers for argument", function[i].type->getPrecisionQualifierString(), "%d", i+1);
973         }
974     }
975 
976     arrayObjectCheck(loc, function.getType(), "array in function return type");
977 
978     if (prototype) {
979         // All built-in functions are defined, even though they don't have a body.
980         // Count their prototype as a definition instead.
981         if (symbolTable.atBuiltInLevel())
982             function.setDefined();
983         else {
984             if (prevDec && ! builtIn)
985                 symbol->getAsFunction()->setPrototyped();  // need a writable one, but like having prevDec as a const
986             function.setPrototyped();
987         }
988     }
989 
990     // This insert won't actually insert it if it's a duplicate signature, but it will still check for
991     // other forms of name collisions.
992     if (! symbolTable.insert(function))
993         error(loc, "function name is redeclaration of existing name", function.getName().c_str(), "");
994 
995     //
996     // If this is a redeclaration, it could also be a definition,
997     // in which case, we need to use the parameter names from this one, and not the one that's
998     // being redeclared.  So, pass back this declaration, not the one in the symbol table.
999     //
1000     return &function;
1001 }
1002 
1003 //
1004 // Handle seeing the function prototype in front of a function definition in the grammar.
1005 // The body is handled after this function returns.
1006 //
handleFunctionDefinition(const TSourceLoc & loc,TFunction & function)1007 TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function)
1008 {
1009     currentCaller = function.getMangledName();
1010     TSymbol* symbol = symbolTable.find(function.getMangledName());
1011     TFunction* prevDec = symbol ? symbol->getAsFunction() : nullptr;
1012 
1013     if (! prevDec)
1014         error(loc, "can't find function", function.getName().c_str(), "");
1015     // Note:  'prevDec' could be 'function' if this is the first time we've seen function
1016     // as it would have just been put in the symbol table.  Otherwise, we're looking up
1017     // an earlier occurrence.
1018 
1019     if (prevDec && prevDec->isDefined()) {
1020         // Then this function already has a body.
1021         error(loc, "function already has a body", function.getName().c_str(), "");
1022     }
1023     if (prevDec && ! prevDec->isDefined()) {
1024         prevDec->setDefined();
1025 
1026         // Remember the return type for later checking for RETURN statements.
1027         currentFunctionType = &(prevDec->getType());
1028     } else
1029         currentFunctionType = new TType(EbtVoid);
1030     functionReturnsValue = false;
1031 
1032     // Check for entry point
1033     if (function.getName().compare(intermediate.getEntryPointName().c_str()) == 0) {
1034         intermediate.setEntryPointMangledName(function.getMangledName().c_str());
1035         intermediate.incrementEntryPointCount();
1036         inMain = true;
1037     } else
1038         inMain = false;
1039 
1040     //
1041     // Raise error message if main function takes any parameters or returns anything other than void
1042     //
1043     if (inMain) {
1044         if (function.getParamCount() > 0)
1045             error(loc, "function cannot take any parameter(s)", function.getName().c_str(), "");
1046         if (function.getType().getBasicType() != EbtVoid)
1047             error(loc, "", function.getType().getBasicTypeString().c_str(), "entry point cannot return a value");
1048     }
1049 
1050     //
1051     // New symbol table scope for body of function plus its arguments
1052     //
1053     symbolTable.push();
1054 
1055     //
1056     // Insert parameters into the symbol table.
1057     // If the parameter has no name, it's not an error, just don't insert it
1058     // (could be used for unused args).
1059     //
1060     // Also, accumulate the list of parameters into the HIL, so lower level code
1061     // knows where to find parameters.
1062     //
1063     TIntermAggregate* paramNodes = new TIntermAggregate;
1064     for (int i = 0; i < function.getParamCount(); i++) {
1065         TParameter& param = function[i];
1066         if (param.name != nullptr) {
1067             TVariable *variable = new TVariable(param.name, *param.type);
1068 
1069             // Insert the parameters with name in the symbol table.
1070             if (! symbolTable.insert(*variable))
1071                 error(loc, "redefinition", variable->getName().c_str(), "");
1072             else {
1073                 // Transfer ownership of name pointer to symbol table.
1074                 param.name = nullptr;
1075 
1076                 // Add the parameter to the HIL
1077                 paramNodes = intermediate.growAggregate(paramNodes,
1078                                                         intermediate.addSymbol(*variable, loc),
1079                                                         loc);
1080             }
1081         } else
1082             paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc);
1083     }
1084     intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc);
1085     loopNestingLevel = 0;
1086     statementNestingLevel = 0;
1087     controlFlowNestingLevel = 0;
1088     postEntryPointReturn = false;
1089 
1090     return paramNodes;
1091 }
1092 
1093 //
1094 // Handle seeing function call syntax in the grammar, which could be any of
1095 //  - .length() method
1096 //  - constructor
1097 //  - a call to a built-in function mapped to an operator
1098 //  - a call to a built-in function that will remain a function call (e.g., texturing)
1099 //  - user function
1100 //  - subroutine call (not implemented yet)
1101 //
handleFunctionCall(const TSourceLoc & loc,TFunction * function,TIntermNode * arguments)1102 TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermNode* arguments)
1103 {
1104     TIntermTyped* result = nullptr;
1105 
1106     if (function->getBuiltInOp() == EOpArrayLength)
1107         result = handleLengthMethod(loc, function, arguments);
1108     else if (function->getBuiltInOp() != EOpNull) {
1109         //
1110         // Then this should be a constructor.
1111         // Don't go through the symbol table for constructors.
1112         // Their parameters will be verified algorithmically.
1113         //
1114         TType type(EbtVoid);  // use this to get the type back
1115         if (! constructorError(loc, arguments, *function, function->getBuiltInOp(), type)) {
1116             //
1117             // It's a constructor, of type 'type'.
1118             //
1119             result = addConstructor(loc, arguments, type);
1120             if (result == nullptr)
1121                 error(loc, "cannot construct with these arguments", type.getCompleteString().c_str(), "");
1122         }
1123     } else {
1124         //
1125         // Find it in the symbol table.
1126         //
1127         const TFunction* fnCandidate;
1128         bool builtIn;
1129         fnCandidate = findFunction(loc, *function, builtIn);
1130         if (fnCandidate) {
1131             // This is a declared function that might map to
1132             //  - a built-in operator,
1133             //  - a built-in function not mapped to an operator, or
1134             //  - a user function.
1135 
1136             // Error check for a function requiring specific extensions present.
1137             if (builtIn && fnCandidate->getNumExtensions())
1138                 requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str());
1139 
1140             if (builtIn && fnCandidate->getType().contains16BitFloat())
1141                 requireFloat16Arithmetic(loc, "built-in function", "float16 types can only be in uniform block or buffer storage");
1142             if (builtIn && fnCandidate->getType().contains16BitInt())
1143                 requireInt16Arithmetic(loc, "built-in function", "(u)int16 types can only be in uniform block or buffer storage");
1144             if (builtIn && fnCandidate->getType().contains8BitInt())
1145                 requireInt8Arithmetic(loc, "built-in function", "(u)int8 types can only be in uniform block or buffer storage");
1146 
1147             if (arguments != nullptr) {
1148                 // Make sure qualifications work for these arguments.
1149                 TIntermAggregate* aggregate = arguments->getAsAggregate();
1150                 for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
1151                     // At this early point there is a slight ambiguity between whether an aggregate 'arguments'
1152                     // is the single argument itself or its children are the arguments.  Only one argument
1153                     // means take 'arguments' itself as the one argument.
1154                     TIntermNode* arg = fnCandidate->getParamCount() == 1 ? arguments : (aggregate ? aggregate->getSequence()[i] : arguments);
1155                     TQualifier& formalQualifier = (*fnCandidate)[i].type->getQualifier();
1156                     if (formalQualifier.isParamOutput()) {
1157                         if (lValueErrorCheck(arguments->getLoc(), "assign", arg->getAsTyped()))
1158                             error(arguments->getLoc(), "Non-L-value cannot be passed for 'out' or 'inout' parameters.", "out", "");
1159                     }
1160                     const TType& argType = arg->getAsTyped()->getType();
1161                     const TQualifier& argQualifier = argType.getQualifier();
1162                     if (argQualifier.isMemory() && (argType.containsOpaque() || argType.isReference())) {
1163                         const char* message = "argument cannot drop memory qualifier when passed to formal parameter";
1164 #ifndef GLSLANG_WEB
1165                         if (argQualifier.volatil && ! formalQualifier.volatil)
1166                             error(arguments->getLoc(), message, "volatile", "");
1167                         if (argQualifier.coherent && ! (formalQualifier.devicecoherent || formalQualifier.coherent))
1168                             error(arguments->getLoc(), message, "coherent", "");
1169                         if (argQualifier.devicecoherent && ! (formalQualifier.devicecoherent || formalQualifier.coherent))
1170                             error(arguments->getLoc(), message, "devicecoherent", "");
1171                         if (argQualifier.queuefamilycoherent && ! (formalQualifier.queuefamilycoherent || formalQualifier.devicecoherent || formalQualifier.coherent))
1172                             error(arguments->getLoc(), message, "queuefamilycoherent", "");
1173                         if (argQualifier.workgroupcoherent && ! (formalQualifier.workgroupcoherent || formalQualifier.queuefamilycoherent || formalQualifier.devicecoherent || formalQualifier.coherent))
1174                             error(arguments->getLoc(), message, "workgroupcoherent", "");
1175                         if (argQualifier.subgroupcoherent && ! (formalQualifier.subgroupcoherent || formalQualifier.workgroupcoherent || formalQualifier.queuefamilycoherent || formalQualifier.devicecoherent || formalQualifier.coherent))
1176                             error(arguments->getLoc(), message, "subgroupcoherent", "");
1177                         if (argQualifier.readonly && ! formalQualifier.readonly)
1178                             error(arguments->getLoc(), message, "readonly", "");
1179                         if (argQualifier.writeonly && ! formalQualifier.writeonly)
1180                             error(arguments->getLoc(), message, "writeonly", "");
1181                         // Don't check 'restrict', it is different than the rest:
1182                         // "...but only restrict can be taken away from a calling argument, by a formal parameter that
1183                         // lacks the restrict qualifier..."
1184 #endif
1185                     }
1186                     if (!builtIn && argQualifier.getFormat() != formalQualifier.getFormat()) {
1187                         // we have mismatched formats, which should only be allowed if writeonly
1188                         // and at least one format is unknown
1189                         if (!formalQualifier.isWriteOnly() || (formalQualifier.getFormat() != ElfNone &&
1190                                                                   argQualifier.getFormat() != ElfNone))
1191                             error(arguments->getLoc(), "image formats must match", "format", "");
1192                     }
1193                     if (builtIn && arg->getAsTyped()->getType().contains16BitFloat())
1194                         requireFloat16Arithmetic(arguments->getLoc(), "built-in function", "float16 types can only be in uniform block or buffer storage");
1195                     if (builtIn && arg->getAsTyped()->getType().contains16BitInt())
1196                         requireInt16Arithmetic(arguments->getLoc(), "built-in function", "(u)int16 types can only be in uniform block or buffer storage");
1197                     if (builtIn && arg->getAsTyped()->getType().contains8BitInt())
1198                         requireInt8Arithmetic(arguments->getLoc(), "built-in function", "(u)int8 types can only be in uniform block or buffer storage");
1199 
1200                     // TODO 4.5 functionality:  A shader will fail to compile
1201                     // if the value passed to the memargument of an atomic memory function does not correspond to a buffer or
1202                     // shared variable. It is acceptable to pass an element of an array or a single component of a vector to the
1203                     // memargument of an atomic memory function, as long as the underlying array or vector is a buffer or
1204                     // shared variable.
1205                 }
1206 
1207                 // Convert 'in' arguments
1208                 addInputArgumentConversions(*fnCandidate, arguments);  // arguments may be modified if it's just a single argument node
1209             }
1210 
1211             if (builtIn && fnCandidate->getBuiltInOp() != EOpNull) {
1212                 // A function call mapped to a built-in operation.
1213                 result = handleBuiltInFunctionCall(loc, arguments, *fnCandidate);
1214             } else {
1215                 // This is a function call not mapped to built-in operator.
1216                 // It could still be a built-in function, but only if PureOperatorBuiltins == false.
1217                 result = intermediate.setAggregateOperator(arguments, EOpFunctionCall, fnCandidate->getType(), loc);
1218                 TIntermAggregate* call = result->getAsAggregate();
1219                 call->setName(fnCandidate->getMangledName());
1220 
1221                 // this is how we know whether the given function is a built-in function or a user-defined function
1222                 // if builtIn == false, it's a userDefined -> could be an overloaded built-in function also
1223                 // if builtIn == true, it's definitely a built-in function with EOpNull
1224                 if (! builtIn) {
1225                     call->setUserDefined();
1226                     if (symbolTable.atGlobalLevel()) {
1227                         requireProfile(loc, ~EEsProfile, "calling user function from global scope");
1228                         intermediate.addToCallGraph(infoSink, "main(", fnCandidate->getMangledName());
1229                     } else
1230                         intermediate.addToCallGraph(infoSink, currentCaller, fnCandidate->getMangledName());
1231                 }
1232 
1233 #ifndef GLSLANG_WEB
1234                 if (builtIn)
1235                     nonOpBuiltInCheck(loc, *fnCandidate, *call);
1236                 else
1237 #endif
1238                     userFunctionCallCheck(loc, *call);
1239             }
1240 
1241             // Convert 'out' arguments.  If it was a constant folded built-in, it won't be an aggregate anymore.
1242             // Built-ins with a single argument aren't called with an aggregate, but they also don't have an output.
1243             // Also, build the qualifier list for user function calls, which are always called with an aggregate.
1244             if (result->getAsAggregate()) {
1245                 TQualifierList& qualifierList = result->getAsAggregate()->getQualifierList();
1246                 for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
1247                     TStorageQualifier qual = (*fnCandidate)[i].type->getQualifier().storage;
1248                     qualifierList.push_back(qual);
1249                 }
1250                 result = addOutputArgumentConversions(*fnCandidate, *result->getAsAggregate());
1251             }
1252 
1253             if (result->getAsTyped()->getType().isCoopMat() &&
1254                !result->getAsTyped()->getType().isParameterized()) {
1255                 assert(fnCandidate->getBuiltInOp() == EOpCooperativeMatrixMulAdd);
1256 
1257                 result->setType(result->getAsAggregate()->getSequence()[2]->getAsTyped()->getType());
1258             }
1259         }
1260     }
1261 
1262     // generic error recovery
1263     // TODO: simplification: localize all the error recoveries that look like this, and taking type into account to reduce cascades
1264     if (result == nullptr)
1265         result = intermediate.addConstantUnion(0.0, EbtFloat, loc);
1266 
1267     return result;
1268 }
1269 
handleBuiltInFunctionCall(TSourceLoc loc,TIntermNode * arguments,const TFunction & function)1270 TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNode* arguments,
1271                                                        const TFunction& function)
1272 {
1273     checkLocation(loc, function.getBuiltInOp());
1274     TIntermTyped *result = intermediate.addBuiltInFunctionCall(loc, function.getBuiltInOp(),
1275                                                                function.getParamCount() == 1,
1276                                                                arguments, function.getType());
1277     if (obeyPrecisionQualifiers())
1278         computeBuiltinPrecisions(*result, function);
1279 
1280     if (result == nullptr) {
1281         if (arguments == nullptr)
1282             error(loc, " wrong operand type", "Internal Error",
1283                                       "built in unary operator function.  Type: %s", "");
1284         else
1285             error(arguments->getLoc(), " wrong operand type", "Internal Error",
1286                                       "built in unary operator function.  Type: %s",
1287                                       static_cast<TIntermTyped*>(arguments)->getCompleteString().c_str());
1288     } else if (result->getAsOperator())
1289         builtInOpCheck(loc, function, *result->getAsOperator());
1290 
1291     return result;
1292 }
1293 
1294 // "The operation of a built-in function can have a different precision
1295 // qualification than the precision qualification of the resulting value.
1296 // These two precision qualifications are established as follows.
1297 //
1298 // The precision qualification of the operation of a built-in function is
1299 // based on the precision qualification of its input arguments and formal
1300 // parameters:  When a formal parameter specifies a precision qualifier,
1301 // that is used, otherwise, the precision qualification of the calling
1302 // argument is used.  The highest precision of these will be the precision
1303 // qualification of the operation of the built-in function. Generally,
1304 // this is applied across all arguments to a built-in function, with the
1305 // exceptions being:
1306 //   - bitfieldExtract and bitfieldInsert ignore the 'offset' and 'bits'
1307 //     arguments.
1308 //   - interpolateAt* functions only look at the 'interpolant' argument.
1309 //
1310 // The precision qualification of the result of a built-in function is
1311 // determined in one of the following ways:
1312 //
1313 //   - For the texture sampling, image load, and image store functions,
1314 //     the precision of the return type matches the precision of the
1315 //     sampler type
1316 //
1317 //   Otherwise:
1318 //
1319 //   - For prototypes that do not specify a resulting precision qualifier,
1320 //     the precision will be the same as the precision of the operation.
1321 //
1322 //   - For prototypes that do specify a resulting precision qualifier,
1323 //     the specified precision qualifier is the precision qualification of
1324 //     the result."
1325 //
computeBuiltinPrecisions(TIntermTyped & node,const TFunction & function)1326 void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction& function)
1327 {
1328     TPrecisionQualifier operationPrecision = EpqNone;
1329     TPrecisionQualifier resultPrecision = EpqNone;
1330 
1331     TIntermOperator* opNode = node.getAsOperator();
1332     if (opNode == nullptr)
1333         return;
1334 
1335     if (TIntermUnary* unaryNode = node.getAsUnaryNode()) {
1336         operationPrecision = std::max(function[0].type->getQualifier().precision,
1337                                       unaryNode->getOperand()->getType().getQualifier().precision);
1338         if (function.getType().getBasicType() != EbtBool)
1339             resultPrecision = function.getType().getQualifier().precision == EpqNone ?
1340                                         operationPrecision :
1341                                         function.getType().getQualifier().precision;
1342     } else if (TIntermAggregate* agg = node.getAsAggregate()) {
1343         TIntermSequence& sequence = agg->getSequence();
1344         unsigned int numArgs = (unsigned int)sequence.size();
1345         switch (agg->getOp()) {
1346         case EOpBitfieldExtract:
1347             numArgs = 1;
1348             break;
1349         case EOpBitfieldInsert:
1350             numArgs = 2;
1351             break;
1352         case EOpInterpolateAtCentroid:
1353         case EOpInterpolateAtOffset:
1354         case EOpInterpolateAtSample:
1355             numArgs = 1;
1356             break;
1357         case EOpDebugPrintf:
1358             numArgs = 0;
1359             break;
1360         default:
1361             break;
1362         }
1363         // find the maximum precision from the arguments and parameters
1364         for (unsigned int arg = 0; arg < numArgs; ++arg) {
1365             operationPrecision = std::max(operationPrecision, sequence[arg]->getAsTyped()->getQualifier().precision);
1366             operationPrecision = std::max(operationPrecision, function[arg].type->getQualifier().precision);
1367         }
1368         // compute the result precision
1369         if (agg->isSampling() ||
1370             agg->getOp() == EOpImageLoad || agg->getOp() == EOpImageStore ||
1371             agg->getOp() == EOpImageLoadLod || agg->getOp() == EOpImageStoreLod)
1372             resultPrecision = sequence[0]->getAsTyped()->getQualifier().precision;
1373         else if (function.getType().getBasicType() != EbtBool)
1374             resultPrecision = function.getType().getQualifier().precision == EpqNone ?
1375                                         operationPrecision :
1376                                         function.getType().getQualifier().precision;
1377     }
1378 
1379     // Propagate precision through this node and its children. That algorithm stops
1380     // when a precision is found, so start by clearing this subroot precision
1381     opNode->getQualifier().precision = EpqNone;
1382     if (operationPrecision != EpqNone) {
1383         opNode->propagatePrecision(operationPrecision);
1384         opNode->setOperationPrecision(operationPrecision);
1385     }
1386     // Now, set the result precision, which might not match
1387     opNode->getQualifier().precision = resultPrecision;
1388 }
1389 
handleReturnValue(const TSourceLoc & loc,TIntermTyped * value)1390 TIntermNode* TParseContext::handleReturnValue(const TSourceLoc& loc, TIntermTyped* value)
1391 {
1392 #ifndef GLSLANG_WEB
1393     storage16BitAssignmentCheck(loc, value->getType(), "return");
1394 #endif
1395 
1396     functionReturnsValue = true;
1397     if (currentFunctionType->getBasicType() == EbtVoid) {
1398         error(loc, "void function cannot return a value", "return", "");
1399         return intermediate.addBranch(EOpReturn, loc);
1400     } else if (*currentFunctionType != value->getType()) {
1401         TIntermTyped* converted = intermediate.addConversion(EOpReturn, *currentFunctionType, value);
1402         if (converted) {
1403             if (*currentFunctionType != converted->getType())
1404                 error(loc, "cannot convert return value to function return type", "return", "");
1405             if (version < 420)
1406                 warn(loc, "type conversion on return values was not explicitly allowed until version 420", "return", "");
1407             return intermediate.addBranch(EOpReturn, converted, loc);
1408         } else {
1409             error(loc, "type does not match, or is not convertible to, the function's return type", "return", "");
1410             return intermediate.addBranch(EOpReturn, value, loc);
1411         }
1412     } else
1413         return intermediate.addBranch(EOpReturn, value, loc);
1414 }
1415 
1416 // See if the operation is being done in an illegal location.
checkLocation(const TSourceLoc & loc,TOperator op)1417 void TParseContext::checkLocation(const TSourceLoc& loc, TOperator op)
1418 {
1419 #ifndef GLSLANG_WEB
1420     switch (op) {
1421     case EOpBarrier:
1422         if (language == EShLangTessControl) {
1423             if (controlFlowNestingLevel > 0)
1424                 error(loc, "tessellation control barrier() cannot be placed within flow control", "", "");
1425             if (! inMain)
1426                 error(loc, "tessellation control barrier() must be in main()", "", "");
1427             else if (postEntryPointReturn)
1428                 error(loc, "tessellation control barrier() cannot be placed after a return from main()", "", "");
1429         }
1430         break;
1431     case EOpBeginInvocationInterlock:
1432         if (language != EShLangFragment)
1433             error(loc, "beginInvocationInterlockARB() must be in a fragment shader", "", "");
1434         if (! inMain)
1435             error(loc, "beginInvocationInterlockARB() must be in main()", "", "");
1436         else if (postEntryPointReturn)
1437             error(loc, "beginInvocationInterlockARB() cannot be placed after a return from main()", "", "");
1438         if (controlFlowNestingLevel > 0)
1439             error(loc, "beginInvocationInterlockARB() cannot be placed within flow control", "", "");
1440 
1441         if (beginInvocationInterlockCount > 0)
1442             error(loc, "beginInvocationInterlockARB() must only be called once", "", "");
1443         if (endInvocationInterlockCount > 0)
1444             error(loc, "beginInvocationInterlockARB() must be called before endInvocationInterlockARB()", "", "");
1445 
1446         beginInvocationInterlockCount++;
1447 
1448         // default to pixel_interlock_ordered
1449         if (intermediate.getInterlockOrdering() == EioNone)
1450             intermediate.setInterlockOrdering(EioPixelInterlockOrdered);
1451         break;
1452     case EOpEndInvocationInterlock:
1453         if (language != EShLangFragment)
1454             error(loc, "endInvocationInterlockARB() must be in a fragment shader", "", "");
1455         if (! inMain)
1456             error(loc, "endInvocationInterlockARB() must be in main()", "", "");
1457         else if (postEntryPointReturn)
1458             error(loc, "endInvocationInterlockARB() cannot be placed after a return from main()", "", "");
1459         if (controlFlowNestingLevel > 0)
1460             error(loc, "endInvocationInterlockARB() cannot be placed within flow control", "", "");
1461 
1462         if (endInvocationInterlockCount > 0)
1463             error(loc, "endInvocationInterlockARB() must only be called once", "", "");
1464         if (beginInvocationInterlockCount == 0)
1465             error(loc, "beginInvocationInterlockARB() must be called before endInvocationInterlockARB()", "", "");
1466 
1467         endInvocationInterlockCount++;
1468         break;
1469     default:
1470         break;
1471     }
1472 #endif
1473 }
1474 
1475 // Finish processing object.length(). This started earlier in handleDotDereference(), where
1476 // the ".length" part was recognized and semantically checked, and finished here where the
1477 // function syntax "()" is recognized.
1478 //
1479 // Return resulting tree node.
handleLengthMethod(const TSourceLoc & loc,TFunction * function,TIntermNode * intermNode)1480 TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction* function, TIntermNode* intermNode)
1481 {
1482     int length = 0;
1483 
1484     if (function->getParamCount() > 0)
1485         error(loc, "method does not accept any arguments", function->getName().c_str(), "");
1486     else {
1487         const TType& type = intermNode->getAsTyped()->getType();
1488         if (type.isArray()) {
1489             if (type.isUnsizedArray()) {
1490 #ifndef GLSLANG_WEB
1491                 if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) {
1492                     // We could be between a layout declaration that gives a built-in io array implicit size and
1493                     // a user redeclaration of that array, meaning we have to substitute its implicit size here
1494                     // without actually redeclaring the array.  (It is an error to use a member before the
1495                     // redeclaration, but not an error to use the array name itself.)
1496                     const TString& name = intermNode->getAsSymbolNode()->getName();
1497                     if (name == "gl_in" || name == "gl_out" || name == "gl_MeshVerticesNV" ||
1498                         name == "gl_MeshPrimitivesNV") {
1499                         length = getIoArrayImplicitSize(type.getQualifier());
1500                     }
1501                 }
1502 #endif
1503                 if (length == 0) {
1504 #ifndef GLSLANG_WEB
1505                     if (intermNode->getAsSymbolNode() && isIoResizeArray(type))
1506                         error(loc, "", function->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier");
1507                     else if (isRuntimeLength(*intermNode->getAsTyped())) {
1508                         // Create a unary op and let the back end handle it
1509                         return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt));
1510                     } else
1511 #endif
1512                         error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method");
1513                 }
1514             } else if (type.getOuterArrayNode()) {
1515                 // If the array's outer size is specified by an intermediate node, it means the array's length
1516                 // was specified by a specialization constant. In such a case, we should return the node of the
1517                 // specialization constants to represent the length.
1518                 return type.getOuterArrayNode();
1519             } else
1520                 length = type.getOuterArraySize();
1521         } else if (type.isMatrix())
1522             length = type.getMatrixCols();
1523         else if (type.isVector())
1524             length = type.getVectorSize();
1525         else if (type.isCoopMat())
1526             return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt));
1527         else {
1528             // we should not get here, because earlier semantic checking should have prevented this path
1529             error(loc, ".length()", "unexpected use of .length()", "");
1530         }
1531     }
1532 
1533     if (length == 0)
1534         length = 1;
1535 
1536     return intermediate.addConstantUnion(length, loc);
1537 }
1538 
1539 //
1540 // Add any needed implicit conversions for function-call arguments to input parameters.
1541 //
addInputArgumentConversions(const TFunction & function,TIntermNode * & arguments) const1542 void TParseContext::addInputArgumentConversions(const TFunction& function, TIntermNode*& arguments) const
1543 {
1544 #ifndef GLSLANG_WEB
1545     TIntermAggregate* aggregate = arguments->getAsAggregate();
1546 
1547     // Process each argument's conversion
1548     for (int i = 0; i < function.getParamCount(); ++i) {
1549         // At this early point there is a slight ambiguity between whether an aggregate 'arguments'
1550         // is the single argument itself or its children are the arguments.  Only one argument
1551         // means take 'arguments' itself as the one argument.
1552         TIntermTyped* arg = function.getParamCount() == 1 ? arguments->getAsTyped() : (aggregate ? aggregate->getSequence()[i]->getAsTyped() : arguments->getAsTyped());
1553         if (*function[i].type != arg->getType()) {
1554             if (function[i].type->getQualifier().isParamInput() &&
1555                !function[i].type->isCoopMat()) {
1556                 // In-qualified arguments just need an extra node added above the argument to
1557                 // convert to the correct type.
1558                 arg = intermediate.addConversion(EOpFunctionCall, *function[i].type, arg);
1559                 if (arg) {
1560                     if (function.getParamCount() == 1)
1561                         arguments = arg;
1562                     else {
1563                         if (aggregate)
1564                             aggregate->getSequence()[i] = arg;
1565                         else
1566                             arguments = arg;
1567                     }
1568                 }
1569             }
1570         }
1571     }
1572 #endif
1573 }
1574 
1575 //
1576 // Add any needed implicit output conversions for function-call arguments.  This
1577 // can require a new tree topology, complicated further by whether the function
1578 // has a return value.
1579 //
1580 // Returns a node of a subtree that evaluates to the return value of the function.
1581 //
addOutputArgumentConversions(const TFunction & function,TIntermAggregate & intermNode) const1582 TIntermTyped* TParseContext::addOutputArgumentConversions(const TFunction& function, TIntermAggregate& intermNode) const
1583 {
1584 #ifdef GLSLANG_WEB
1585     return &intermNode;
1586 #else
1587     TIntermSequence& arguments = intermNode.getSequence();
1588 
1589     // Will there be any output conversions?
1590     bool outputConversions = false;
1591     for (int i = 0; i < function.getParamCount(); ++i) {
1592         if (*function[i].type != arguments[i]->getAsTyped()->getType() && function[i].type->getQualifier().isParamOutput()) {
1593             outputConversions = true;
1594             break;
1595         }
1596     }
1597 
1598     if (! outputConversions)
1599         return &intermNode;
1600 
1601     // Setup for the new tree, if needed:
1602     //
1603     // Output conversions need a different tree topology.
1604     // Out-qualified arguments need a temporary of the correct type, with the call
1605     // followed by an assignment of the temporary to the original argument:
1606     //     void: function(arg, ...)  ->        (          function(tempArg, ...), arg = tempArg, ...)
1607     //     ret = function(arg, ...)  ->  ret = (tempRet = function(tempArg, ...), arg = tempArg, ..., tempRet)
1608     // Where the "tempArg" type needs no conversion as an argument, but will convert on assignment.
1609     TIntermTyped* conversionTree = nullptr;
1610     TVariable* tempRet = nullptr;
1611     if (intermNode.getBasicType() != EbtVoid) {
1612         // do the "tempRet = function(...), " bit from above
1613         tempRet = makeInternalVariable("tempReturn", intermNode.getType());
1614         TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc());
1615         conversionTree = intermediate.addAssign(EOpAssign, tempRetNode, &intermNode, intermNode.getLoc());
1616     } else
1617         conversionTree = &intermNode;
1618 
1619     conversionTree = intermediate.makeAggregate(conversionTree);
1620 
1621     // Process each argument's conversion
1622     for (int i = 0; i < function.getParamCount(); ++i) {
1623         if (*function[i].type != arguments[i]->getAsTyped()->getType()) {
1624             if (function[i].type->getQualifier().isParamOutput()) {
1625                 // Out-qualified arguments need to use the topology set up above.
1626                 // do the " ...(tempArg, ...), arg = tempArg" bit from above
1627                 TType paramType;
1628                 paramType.shallowCopy(*function[i].type);
1629                 if (arguments[i]->getAsTyped()->getType().isParameterized() &&
1630                     !paramType.isParameterized()) {
1631                     paramType.shallowCopy(arguments[i]->getAsTyped()->getType());
1632                     paramType.copyTypeParameters(*arguments[i]->getAsTyped()->getType().getTypeParameters());
1633                 }
1634                 TVariable* tempArg = makeInternalVariable("tempArg", paramType);
1635                 tempArg->getWritableType().getQualifier().makeTemporary();
1636                 TIntermSymbol* tempArgNode = intermediate.addSymbol(*tempArg, intermNode.getLoc());
1637                 TIntermTyped* tempAssign = intermediate.addAssign(EOpAssign, arguments[i]->getAsTyped(), tempArgNode, arguments[i]->getLoc());
1638                 conversionTree = intermediate.growAggregate(conversionTree, tempAssign, arguments[i]->getLoc());
1639                 // replace the argument with another node for the same tempArg variable
1640                 arguments[i] = intermediate.addSymbol(*tempArg, intermNode.getLoc());
1641             }
1642         }
1643     }
1644 
1645     // Finalize the tree topology (see bigger comment above).
1646     if (tempRet) {
1647         // do the "..., tempRet" bit from above
1648         TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc());
1649         conversionTree = intermediate.growAggregate(conversionTree, tempRetNode, intermNode.getLoc());
1650     }
1651     conversionTree = intermediate.setAggregateOperator(conversionTree, EOpComma, intermNode.getType(), intermNode.getLoc());
1652 
1653     return conversionTree;
1654 #endif
1655 }
1656 
memorySemanticsCheck(const TSourceLoc & loc,const TFunction & fnCandidate,const TIntermOperator & callNode)1657 void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction& fnCandidate, const TIntermOperator& callNode)
1658 {
1659     const TIntermSequence* argp = &callNode.getAsAggregate()->getSequence();
1660 
1661     //const int gl_SemanticsRelaxed         = 0x0;
1662     const int gl_SemanticsAcquire         = 0x2;
1663     const int gl_SemanticsRelease         = 0x4;
1664     const int gl_SemanticsAcquireRelease  = 0x8;
1665     const int gl_SemanticsMakeAvailable   = 0x2000;
1666     const int gl_SemanticsMakeVisible     = 0x4000;
1667     const int gl_SemanticsVolatile        = 0x8000;
1668 
1669     //const int gl_StorageSemanticsNone     = 0x0;
1670     const int gl_StorageSemanticsBuffer   = 0x40;
1671     const int gl_StorageSemanticsShared   = 0x100;
1672     const int gl_StorageSemanticsImage    = 0x800;
1673     const int gl_StorageSemanticsOutput   = 0x1000;
1674 
1675 
1676     unsigned int semantics = 0, storageClassSemantics = 0;
1677     unsigned int semantics2 = 0, storageClassSemantics2 = 0;
1678 
1679     const TIntermTyped* arg0 = (*argp)[0]->getAsTyped();
1680     const bool isMS = arg0->getBasicType() == EbtSampler && arg0->getType().getSampler().isMultiSample();
1681 
1682     // Grab the semantics and storage class semantics from the operands, based on opcode
1683     switch (callNode.getOp()) {
1684     case EOpAtomicAdd:
1685     case EOpAtomicMin:
1686     case EOpAtomicMax:
1687     case EOpAtomicAnd:
1688     case EOpAtomicOr:
1689     case EOpAtomicXor:
1690     case EOpAtomicExchange:
1691     case EOpAtomicStore:
1692         storageClassSemantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst();
1693         semantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst();
1694         break;
1695     case EOpAtomicLoad:
1696         storageClassSemantics = (*argp)[2]->getAsConstantUnion()->getConstArray()[0].getIConst();
1697         semantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst();
1698         break;
1699     case EOpAtomicCompSwap:
1700         storageClassSemantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst();
1701         semantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst();
1702         storageClassSemantics2 = (*argp)[6]->getAsConstantUnion()->getConstArray()[0].getIConst();
1703         semantics2 = (*argp)[7]->getAsConstantUnion()->getConstArray()[0].getIConst();
1704         break;
1705 
1706     case EOpImageAtomicAdd:
1707     case EOpImageAtomicMin:
1708     case EOpImageAtomicMax:
1709     case EOpImageAtomicAnd:
1710     case EOpImageAtomicOr:
1711     case EOpImageAtomicXor:
1712     case EOpImageAtomicExchange:
1713     case EOpImageAtomicStore:
1714         storageClassSemantics = (*argp)[isMS ? 5 : 4]->getAsConstantUnion()->getConstArray()[0].getIConst();
1715         semantics = (*argp)[isMS ? 6 : 5]->getAsConstantUnion()->getConstArray()[0].getIConst();
1716         break;
1717     case EOpImageAtomicLoad:
1718         storageClassSemantics = (*argp)[isMS ? 4 : 3]->getAsConstantUnion()->getConstArray()[0].getIConst();
1719         semantics = (*argp)[isMS ? 5 : 4]->getAsConstantUnion()->getConstArray()[0].getIConst();
1720         break;
1721     case EOpImageAtomicCompSwap:
1722         storageClassSemantics = (*argp)[isMS ? 6 : 5]->getAsConstantUnion()->getConstArray()[0].getIConst();
1723         semantics = (*argp)[isMS ? 7 : 6]->getAsConstantUnion()->getConstArray()[0].getIConst();
1724         storageClassSemantics2 = (*argp)[isMS ? 8 : 7]->getAsConstantUnion()->getConstArray()[0].getIConst();
1725         semantics2 = (*argp)[isMS ? 9 : 8]->getAsConstantUnion()->getConstArray()[0].getIConst();
1726         break;
1727 
1728     case EOpBarrier:
1729         storageClassSemantics = (*argp)[2]->getAsConstantUnion()->getConstArray()[0].getIConst();
1730         semantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst();
1731         break;
1732     case EOpMemoryBarrier:
1733         storageClassSemantics = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getIConst();
1734         semantics = (*argp)[2]->getAsConstantUnion()->getConstArray()[0].getIConst();
1735         break;
1736     default:
1737         break;
1738     }
1739 
1740     if ((semantics & gl_SemanticsAcquire) &&
1741         (callNode.getOp() == EOpAtomicStore || callNode.getOp() == EOpImageAtomicStore)) {
1742         error(loc, "gl_SemanticsAcquire must not be used with (image) atomic store",
1743               fnCandidate.getName().c_str(), "");
1744     }
1745     if ((semantics & gl_SemanticsRelease) &&
1746         (callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpImageAtomicLoad)) {
1747         error(loc, "gl_SemanticsRelease must not be used with (image) atomic load",
1748               fnCandidate.getName().c_str(), "");
1749     }
1750     if ((semantics & gl_SemanticsAcquireRelease) &&
1751         (callNode.getOp() == EOpAtomicStore || callNode.getOp() == EOpImageAtomicStore ||
1752          callNode.getOp() == EOpAtomicLoad  || callNode.getOp() == EOpImageAtomicLoad)) {
1753         error(loc, "gl_SemanticsAcquireRelease must not be used with (image) atomic load/store",
1754               fnCandidate.getName().c_str(), "");
1755     }
1756     if (((semantics | semantics2) & ~(gl_SemanticsAcquire |
1757                                       gl_SemanticsRelease |
1758                                       gl_SemanticsAcquireRelease |
1759                                       gl_SemanticsMakeAvailable |
1760                                       gl_SemanticsMakeVisible |
1761                                       gl_SemanticsVolatile))) {
1762         error(loc, "Invalid semantics value", fnCandidate.getName().c_str(), "");
1763     }
1764     if (((storageClassSemantics | storageClassSemantics2) & ~(gl_StorageSemanticsBuffer |
1765                                                               gl_StorageSemanticsShared |
1766                                                               gl_StorageSemanticsImage |
1767                                                               gl_StorageSemanticsOutput))) {
1768         error(loc, "Invalid storage class semantics value", fnCandidate.getName().c_str(), "");
1769     }
1770 
1771     if (callNode.getOp() == EOpMemoryBarrier) {
1772         if (!IsPow2(semantics & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease))) {
1773             error(loc, "Semantics must include exactly one of gl_SemanticsRelease, gl_SemanticsAcquire, or "
1774                        "gl_SemanticsAcquireRelease", fnCandidate.getName().c_str(), "");
1775         }
1776     } else {
1777         if (semantics & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease)) {
1778             if (!IsPow2(semantics & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease))) {
1779                 error(loc, "Semantics must not include multiple of gl_SemanticsRelease, gl_SemanticsAcquire, or "
1780                            "gl_SemanticsAcquireRelease", fnCandidate.getName().c_str(), "");
1781             }
1782         }
1783         if (semantics2 & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease)) {
1784             if (!IsPow2(semantics2 & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease))) {
1785                 error(loc, "semUnequal must not include multiple of gl_SemanticsRelease, gl_SemanticsAcquire, or "
1786                            "gl_SemanticsAcquireRelease", fnCandidate.getName().c_str(), "");
1787             }
1788         }
1789     }
1790     if (callNode.getOp() == EOpMemoryBarrier) {
1791         if (storageClassSemantics == 0) {
1792             error(loc, "Storage class semantics must not be zero", fnCandidate.getName().c_str(), "");
1793         }
1794     }
1795     if (callNode.getOp() == EOpBarrier && semantics != 0 && storageClassSemantics == 0) {
1796         error(loc, "Storage class semantics must not be zero", fnCandidate.getName().c_str(), "");
1797     }
1798     if ((callNode.getOp() == EOpAtomicCompSwap || callNode.getOp() == EOpImageAtomicCompSwap) &&
1799         (semantics2 & (gl_SemanticsRelease | gl_SemanticsAcquireRelease))) {
1800         error(loc, "semUnequal must not be gl_SemanticsRelease or gl_SemanticsAcquireRelease",
1801               fnCandidate.getName().c_str(), "");
1802     }
1803     if ((semantics & gl_SemanticsMakeAvailable) &&
1804         !(semantics & (gl_SemanticsRelease | gl_SemanticsAcquireRelease))) {
1805         error(loc, "gl_SemanticsMakeAvailable requires gl_SemanticsRelease or gl_SemanticsAcquireRelease",
1806               fnCandidate.getName().c_str(), "");
1807     }
1808     if ((semantics & gl_SemanticsMakeVisible) &&
1809         !(semantics & (gl_SemanticsAcquire | gl_SemanticsAcquireRelease))) {
1810         error(loc, "gl_SemanticsMakeVisible requires gl_SemanticsAcquire or gl_SemanticsAcquireRelease",
1811               fnCandidate.getName().c_str(), "");
1812     }
1813     if ((semantics & gl_SemanticsVolatile) &&
1814         (callNode.getOp() == EOpMemoryBarrier || callNode.getOp() == EOpBarrier)) {
1815         error(loc, "gl_SemanticsVolatile must not be used with memoryBarrier or controlBarrier",
1816               fnCandidate.getName().c_str(), "");
1817     }
1818     if ((callNode.getOp() == EOpAtomicCompSwap || callNode.getOp() == EOpImageAtomicCompSwap) &&
1819         ((semantics ^ semantics2) & gl_SemanticsVolatile)) {
1820         error(loc, "semEqual and semUnequal must either both include gl_SemanticsVolatile or neither",
1821               fnCandidate.getName().c_str(), "");
1822     }
1823 }
1824 
1825 //
1826 // Do additional checking of built-in function calls that is not caught
1827 // by normal semantic checks on argument type, extension tagging, etc.
1828 //
1829 // Assumes there has been a semantically correct match to a built-in function prototype.
1830 //
builtInOpCheck(const TSourceLoc & loc,const TFunction & fnCandidate,TIntermOperator & callNode)1831 void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermOperator& callNode)
1832 {
1833     // Set up convenience accessors to the argument(s).  There is almost always
1834     // multiple arguments for the cases below, but when there might be one,
1835     // check the unaryArg first.
1836     const TIntermSequence* argp = nullptr;   // confusing to use [] syntax on a pointer, so this is to help get a reference
1837     const TIntermTyped* unaryArg = nullptr;
1838     const TIntermTyped* arg0 = nullptr;
1839     if (callNode.getAsAggregate()) {
1840         argp = &callNode.getAsAggregate()->getSequence();
1841         if (argp->size() > 0)
1842             arg0 = (*argp)[0]->getAsTyped();
1843     } else {
1844         assert(callNode.getAsUnaryNode());
1845         unaryArg = callNode.getAsUnaryNode()->getOperand();
1846         arg0 = unaryArg;
1847     }
1848 
1849     TString featureString;
1850     const char* feature = nullptr;
1851     switch (callNode.getOp()) {
1852 #ifndef GLSLANG_WEB
1853     case EOpTextureGather:
1854     case EOpTextureGatherOffset:
1855     case EOpTextureGatherOffsets:
1856     {
1857         // Figure out which variants are allowed by what extensions,
1858         // and what arguments must be constant for which situations.
1859 
1860         featureString = fnCandidate.getName();
1861         featureString += "(...)";
1862         feature = featureString.c_str();
1863         profileRequires(loc, EEsProfile, 310, nullptr, feature);
1864         int compArg = -1;  // track which argument, if any, is the constant component argument
1865         switch (callNode.getOp()) {
1866         case EOpTextureGather:
1867             // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5,
1868             // otherwise, need GL_ARB_texture_gather.
1869             if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) {
1870                 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
1871                 if (! fnCandidate[0].type->getSampler().shadow)
1872                     compArg = 2;
1873             } else
1874                 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
1875             break;
1876         case EOpTextureGatherOffset:
1877             // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument
1878             if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3)
1879                 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
1880             else
1881                 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
1882             if (! (*argp)[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion())
1883                 profileRequires(loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5,
1884                                 "non-constant offset argument");
1885             if (! fnCandidate[0].type->getSampler().shadow)
1886                 compArg = 3;
1887             break;
1888         case EOpTextureGatherOffsets:
1889             profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
1890             if (! fnCandidate[0].type->getSampler().shadow)
1891                 compArg = 3;
1892             // check for constant offsets
1893             if (! (*argp)[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion())
1894                 error(loc, "must be a compile-time constant:", feature, "offsets argument");
1895             break;
1896         default:
1897             break;
1898         }
1899 
1900         if (compArg > 0 && compArg < fnCandidate.getParamCount()) {
1901             if ((*argp)[compArg]->getAsConstantUnion()) {
1902                 int value = (*argp)[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst();
1903                 if (value < 0 || value > 3)
1904                     error(loc, "must be 0, 1, 2, or 3:", feature, "component argument");
1905             } else
1906                 error(loc, "must be a compile-time constant:", feature, "component argument");
1907         }
1908 
1909         bool bias = false;
1910         if (callNode.getOp() == EOpTextureGather)
1911             bias = fnCandidate.getParamCount() > 3;
1912         else if (callNode.getOp() == EOpTextureGatherOffset ||
1913                  callNode.getOp() == EOpTextureGatherOffsets)
1914             bias = fnCandidate.getParamCount() > 4;
1915 
1916         if (bias) {
1917             featureString = fnCandidate.getName();
1918             featureString += "with bias argument";
1919             feature = featureString.c_str();
1920             profileRequires(loc, ~EEsProfile, 450, nullptr, feature);
1921             requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature);
1922         }
1923         break;
1924     }
1925     case EOpSparseTextureGather:
1926     case EOpSparseTextureGatherOffset:
1927     case EOpSparseTextureGatherOffsets:
1928     {
1929         bool bias = false;
1930         if (callNode.getOp() == EOpSparseTextureGather)
1931             bias = fnCandidate.getParamCount() > 4;
1932         else if (callNode.getOp() == EOpSparseTextureGatherOffset ||
1933                  callNode.getOp() == EOpSparseTextureGatherOffsets)
1934             bias = fnCandidate.getParamCount() > 5;
1935 
1936         if (bias) {
1937             featureString = fnCandidate.getName();
1938             featureString += "with bias argument";
1939             feature = featureString.c_str();
1940             profileRequires(loc, ~EEsProfile, 450, nullptr, feature);
1941             requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature);
1942         }
1943 
1944         break;
1945     }
1946 
1947     case EOpSparseTextureGatherLod:
1948     case EOpSparseTextureGatherLodOffset:
1949     case EOpSparseTextureGatherLodOffsets:
1950     {
1951         requireExtensions(loc, 1, &E_GL_ARB_sparse_texture2, fnCandidate.getName().c_str());
1952         break;
1953     }
1954 
1955     case EOpSwizzleInvocations:
1956     {
1957         if (! (*argp)[1]->getAsConstantUnion())
1958             error(loc, "argument must be compile-time constant", "offset", "");
1959         else {
1960             unsigned offset[4] = {};
1961             offset[0] = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst();
1962             offset[1] = (*argp)[1]->getAsConstantUnion()->getConstArray()[1].getUConst();
1963             offset[2] = (*argp)[1]->getAsConstantUnion()->getConstArray()[2].getUConst();
1964             offset[3] = (*argp)[1]->getAsConstantUnion()->getConstArray()[3].getUConst();
1965             if (offset[0] > 3 || offset[1] > 3 || offset[2] > 3 || offset[3] > 3)
1966                 error(loc, "components must be in the range [0, 3]", "offset", "");
1967         }
1968 
1969         break;
1970     }
1971 
1972     case EOpSwizzleInvocationsMasked:
1973     {
1974         if (! (*argp)[1]->getAsConstantUnion())
1975             error(loc, "argument must be compile-time constant", "mask", "");
1976         else {
1977             unsigned mask[3] = {};
1978             mask[0] = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst();
1979             mask[1] = (*argp)[1]->getAsConstantUnion()->getConstArray()[1].getUConst();
1980             mask[2] = (*argp)[1]->getAsConstantUnion()->getConstArray()[2].getUConst();
1981             if (mask[0] > 31 || mask[1] > 31 || mask[2] > 31)
1982                 error(loc, "components must be in the range [0, 31]", "mask", "");
1983         }
1984 
1985         break;
1986     }
1987 #endif
1988 
1989     case EOpTextureOffset:
1990     case EOpTextureFetchOffset:
1991     case EOpTextureProjOffset:
1992     case EOpTextureLodOffset:
1993     case EOpTextureProjLodOffset:
1994     case EOpTextureGradOffset:
1995     case EOpTextureProjGradOffset:
1996     {
1997         // Handle texture-offset limits checking
1998         // Pick which argument has to hold constant offsets
1999         int arg = -1;
2000         switch (callNode.getOp()) {
2001         case EOpTextureOffset:          arg = 2;  break;
2002         case EOpTextureFetchOffset:     arg = (arg0->getType().getSampler().isRect()) ? 2 : 3; break;
2003         case EOpTextureProjOffset:      arg = 2;  break;
2004         case EOpTextureLodOffset:       arg = 3;  break;
2005         case EOpTextureProjLodOffset:   arg = 3;  break;
2006         case EOpTextureGradOffset:      arg = 4;  break;
2007         case EOpTextureProjGradOffset:  arg = 4;  break;
2008         default:
2009             assert(0);
2010             break;
2011         }
2012 
2013         if (arg > 0) {
2014 
2015 #ifndef GLSLANG_WEB
2016             bool f16ShadowCompare = (*argp)[1]->getAsTyped()->getBasicType() == EbtFloat16 &&
2017                                     arg0->getType().getSampler().shadow;
2018             if (f16ShadowCompare)
2019                 ++arg;
2020 #endif
2021             if (! (*argp)[arg]->getAsTyped()->getQualifier().isConstant())
2022                 error(loc, "argument must be compile-time constant", "texel offset", "");
2023             else if ((*argp)[arg]->getAsConstantUnion()) {
2024                 const TType& type = (*argp)[arg]->getAsTyped()->getType();
2025                 for (int c = 0; c < type.getVectorSize(); ++c) {
2026                     int offset = (*argp)[arg]->getAsConstantUnion()->getConstArray()[c].getIConst();
2027                     if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset)
2028                         error(loc, "value is out of range:", "texel offset",
2029                               "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
2030                 }
2031             }
2032         }
2033 
2034         break;
2035     }
2036 
2037 #ifndef GLSLANG_WEB
2038     case EOpTrace:
2039         if (!(*argp)[10]->getAsConstantUnion())
2040             error(loc, "argument must be compile-time constant", "payload number", "");
2041         break;
2042     case EOpExecuteCallable:
2043         if (!(*argp)[1]->getAsConstantUnion())
2044             error(loc, "argument must be compile-time constant", "callable data number", "");
2045         break;
2046 
2047     case EOpRayQueryGetIntersectionType:
2048     case EOpRayQueryGetIntersectionT:
2049     case EOpRayQueryGetIntersectionInstanceCustomIndex:
2050     case EOpRayQueryGetIntersectionInstanceId:
2051     case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset:
2052     case EOpRayQueryGetIntersectionGeometryIndex:
2053     case EOpRayQueryGetIntersectionPrimitiveIndex:
2054     case EOpRayQueryGetIntersectionBarycentrics:
2055     case EOpRayQueryGetIntersectionFrontFace:
2056     case EOpRayQueryGetIntersectionObjectRayDirection:
2057     case EOpRayQueryGetIntersectionObjectRayOrigin:
2058     case EOpRayQueryGetIntersectionObjectToWorld:
2059     case EOpRayQueryGetIntersectionWorldToObject:
2060         if (!(*argp)[1]->getAsConstantUnion())
2061             error(loc, "argument must be compile-time constant", "committed", "");
2062         break;
2063 
2064     case EOpTextureQuerySamples:
2065     case EOpImageQuerySamples:
2066         // GL_ARB_shader_texture_image_samples
2067         profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples");
2068         break;
2069 
2070     case EOpImageAtomicAdd:
2071     case EOpImageAtomicMin:
2072     case EOpImageAtomicMax:
2073     case EOpImageAtomicAnd:
2074     case EOpImageAtomicOr:
2075     case EOpImageAtomicXor:
2076     case EOpImageAtomicExchange:
2077     case EOpImageAtomicCompSwap:
2078     case EOpImageAtomicLoad:
2079     case EOpImageAtomicStore:
2080     {
2081         // Make sure the image types have the correct layout() format and correct argument types
2082         const TType& imageType = arg0->getType();
2083         if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) {
2084             if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui)
2085                 error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), "");
2086         } else {
2087             if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0)
2088                 error(loc, "only supported on integer images", fnCandidate.getName().c_str(), "");
2089             else if (imageType.getQualifier().getFormat() != ElfR32f && isEsProfile())
2090                 error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), "");
2091         }
2092 
2093         const size_t maxArgs = imageType.getSampler().isMultiSample() ? 5 : 4;
2094         if (argp->size() > maxArgs) {
2095             requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str());
2096             memorySemanticsCheck(loc, fnCandidate, callNode);
2097         }
2098 
2099         break;
2100     }
2101 
2102     case EOpAtomicAdd:
2103     case EOpAtomicMin:
2104     case EOpAtomicMax:
2105     case EOpAtomicAnd:
2106     case EOpAtomicOr:
2107     case EOpAtomicXor:
2108     case EOpAtomicExchange:
2109     case EOpAtomicCompSwap:
2110     case EOpAtomicLoad:
2111     case EOpAtomicStore:
2112     {
2113         if (argp->size() > 3) {
2114             requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str());
2115             memorySemanticsCheck(loc, fnCandidate, callNode);
2116         } else if (arg0->getType().getBasicType() == EbtInt64 || arg0->getType().getBasicType() == EbtUint64) {
2117             const char* const extensions[2] = { E_GL_NV_shader_atomic_int64,
2118                                                 E_GL_EXT_shader_atomic_int64 };
2119             requireExtensions(loc, 2, extensions, fnCandidate.getName().c_str());
2120         }
2121         break;
2122     }
2123 
2124     case EOpInterpolateAtCentroid:
2125     case EOpInterpolateAtSample:
2126     case EOpInterpolateAtOffset:
2127     case EOpInterpolateAtVertex:
2128         // Make sure the first argument is an interpolant, or an array element of an interpolant
2129         if (arg0->getType().getQualifier().storage != EvqVaryingIn) {
2130             // It might still be an array element.
2131             //
2132             // We could check more, but the semantics of the first argument are already met; the
2133             // only way to turn an array into a float/vec* is array dereference and swizzle.
2134             //
2135             // ES and desktop 4.3 and earlier:  swizzles may not be used
2136             // desktop 4.4 and later: swizzles may be used
2137             bool swizzleOkay = (!isEsProfile()) && (version >= 440);
2138             const TIntermTyped* base = TIntermediate::findLValueBase(arg0, swizzleOkay);
2139             if (base == nullptr || base->getType().getQualifier().storage != EvqVaryingIn)
2140                 error(loc, "first argument must be an interpolant, or interpolant-array element", fnCandidate.getName().c_str(), "");
2141         }
2142 
2143         if (callNode.getOp() == EOpInterpolateAtVertex) {
2144             if (!arg0->getType().getQualifier().isExplicitInterpolation())
2145                 error(loc, "argument must be qualified as __explicitInterpAMD in", "interpolant", "");
2146             else {
2147                 if (! (*argp)[1]->getAsConstantUnion())
2148                     error(loc, "argument must be compile-time constant", "vertex index", "");
2149                 else {
2150                     unsigned vertexIdx = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst();
2151                     if (vertexIdx > 2)
2152                         error(loc, "must be in the range [0, 2]", "vertex index", "");
2153                 }
2154             }
2155         }
2156         break;
2157 
2158     case EOpEmitStreamVertex:
2159     case EOpEndStreamPrimitive:
2160         intermediate.setMultiStream();
2161         break;
2162 
2163     case EOpSubgroupClusteredAdd:
2164     case EOpSubgroupClusteredMul:
2165     case EOpSubgroupClusteredMin:
2166     case EOpSubgroupClusteredMax:
2167     case EOpSubgroupClusteredAnd:
2168     case EOpSubgroupClusteredOr:
2169     case EOpSubgroupClusteredXor:
2170         // The <clusterSize> as used in the subgroupClustered<op>() operations must be:
2171         // - An integral constant expression.
2172         // - At least 1.
2173         // - A power of 2.
2174         if ((*argp)[1]->getAsConstantUnion() == nullptr)
2175             error(loc, "argument must be compile-time constant", "cluster size", "");
2176         else {
2177             int size = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getIConst();
2178             if (size < 1)
2179                 error(loc, "argument must be at least 1", "cluster size", "");
2180             else if (!IsPow2(size))
2181                 error(loc, "argument must be a power of 2", "cluster size", "");
2182         }
2183         break;
2184 
2185     case EOpSubgroupBroadcast:
2186     case EOpSubgroupQuadBroadcast:
2187         if (spvVersion.spv < EShTargetSpv_1_5) {
2188             // <id> must be an integral constant expression.
2189             if ((*argp)[1]->getAsConstantUnion() == nullptr)
2190                 error(loc, "argument must be compile-time constant", "id", "");
2191         }
2192         break;
2193 
2194     case EOpBarrier:
2195     case EOpMemoryBarrier:
2196         if (argp->size() > 0) {
2197             requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str());
2198             memorySemanticsCheck(loc, fnCandidate, callNode);
2199         }
2200         break;
2201 #endif
2202 
2203     default:
2204         break;
2205     }
2206 
2207     // Texture operations on texture objects (aside from texelFetch on a
2208     // textureBuffer) require EXT_samplerless_texture_functions.
2209     switch (callNode.getOp()) {
2210     case EOpTextureQuerySize:
2211     case EOpTextureQueryLevels:
2212     case EOpTextureQuerySamples:
2213     case EOpTextureFetch:
2214     case EOpTextureFetchOffset:
2215     {
2216         const TSampler& sampler = fnCandidate[0].type->getSampler();
2217 
2218         const bool isTexture = sampler.isTexture() && !sampler.isCombined();
2219         const bool isBuffer = sampler.isBuffer();
2220         const bool isFetch = callNode.getOp() == EOpTextureFetch || callNode.getOp() == EOpTextureFetchOffset;
2221 
2222         if (isTexture && (!isBuffer || !isFetch))
2223             requireExtensions(loc, 1, &E_GL_EXT_samplerless_texture_functions, fnCandidate.getName().c_str());
2224 
2225         break;
2226     }
2227 
2228     default:
2229         break;
2230     }
2231 
2232     if (callNode.isSubgroup()) {
2233         // these require SPIR-V 1.3
2234         if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_3)
2235             error(loc, "requires SPIR-V 1.3", "subgroup op", "");
2236 
2237         // Check that if extended types are being used that the correct extensions are enabled.
2238         if (arg0 != nullptr) {
2239             const TType& type = arg0->getType();
2240             switch (type.getBasicType()) {
2241             default:
2242                 break;
2243             case EbtInt8:
2244             case EbtUint8:
2245                 requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int8, type.getCompleteString().c_str());
2246                 break;
2247             case EbtInt16:
2248             case EbtUint16:
2249                 requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int16, type.getCompleteString().c_str());
2250                 break;
2251             case EbtInt64:
2252             case EbtUint64:
2253                 requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int64, type.getCompleteString().c_str());
2254                 break;
2255             case EbtFloat16:
2256                 requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_float16, type.getCompleteString().c_str());
2257                 break;
2258             }
2259         }
2260     }
2261 }
2262 
2263 #ifndef GLSLANG_WEB
2264 
2265 extern bool PureOperatorBuiltins;
2266 
2267 // Deprecated!  Use PureOperatorBuiltins == true instead, in which case this
2268 // functionality is handled in builtInOpCheck() instead of here.
2269 //
2270 // Do additional checking of built-in function calls that were not mapped
2271 // to built-in operations (e.g., texturing functions).
2272 //
2273 // Assumes there has been a semantically correct match to a built-in function.
2274 //
nonOpBuiltInCheck(const TSourceLoc & loc,const TFunction & fnCandidate,TIntermAggregate & callNode)2275 void TParseContext::nonOpBuiltInCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermAggregate& callNode)
2276 {
2277     // Further maintenance of this function is deprecated, because the "correct"
2278     // future-oriented design is to not have to do string compares on function names.
2279 
2280     // If PureOperatorBuiltins == true, then all built-ins should be mapped
2281     // to a TOperator, and this function would then never get called.
2282 
2283     assert(PureOperatorBuiltins == false);
2284 
2285     // built-in texturing functions get their return value precision from the precision of the sampler
2286     if (fnCandidate.getType().getQualifier().precision == EpqNone &&
2287         fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler)
2288         callNode.getQualifier().precision = callNode.getSequence()[0]->getAsTyped()->getQualifier().precision;
2289 
2290     if (fnCandidate.getName().compare(0, 7, "texture") == 0) {
2291         if (fnCandidate.getName().compare(0, 13, "textureGather") == 0) {
2292             TString featureString = fnCandidate.getName() + "(...)";
2293             const char* feature = featureString.c_str();
2294             profileRequires(loc, EEsProfile, 310, nullptr, feature);
2295 
2296             int compArg = -1;  // track which argument, if any, is the constant component argument
2297             if (fnCandidate.getName().compare("textureGatherOffset") == 0) {
2298                 // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument
2299                 if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3)
2300                     profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
2301                 else
2302                     profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
2303                 int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2;
2304                 if (! callNode.getSequence()[offsetArg]->getAsConstantUnion())
2305                     profileRequires(loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5,
2306                                     "non-constant offset argument");
2307                 if (! fnCandidate[0].type->getSampler().shadow)
2308                     compArg = 3;
2309             } else if (fnCandidate.getName().compare("textureGatherOffsets") == 0) {
2310                 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
2311                 if (! fnCandidate[0].type->getSampler().shadow)
2312                     compArg = 3;
2313                 // check for constant offsets
2314                 int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2;
2315                 if (! callNode.getSequence()[offsetArg]->getAsConstantUnion())
2316                     error(loc, "must be a compile-time constant:", feature, "offsets argument");
2317             } else if (fnCandidate.getName().compare("textureGather") == 0) {
2318                 // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5,
2319                 // otherwise, need GL_ARB_texture_gather.
2320                 if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) {
2321                     profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
2322                     if (! fnCandidate[0].type->getSampler().shadow)
2323                         compArg = 2;
2324                 } else
2325                     profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
2326             }
2327 
2328             if (compArg > 0 && compArg < fnCandidate.getParamCount()) {
2329                 if (callNode.getSequence()[compArg]->getAsConstantUnion()) {
2330                     int value = callNode.getSequence()[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst();
2331                     if (value < 0 || value > 3)
2332                         error(loc, "must be 0, 1, 2, or 3:", feature, "component argument");
2333                 } else
2334                     error(loc, "must be a compile-time constant:", feature, "component argument");
2335             }
2336         } else {
2337             // this is only for functions not starting "textureGather"...
2338             if (fnCandidate.getName().find("Offset") != TString::npos) {
2339 
2340                 // Handle texture-offset limits checking
2341                 int arg = -1;
2342                 if (fnCandidate.getName().compare("textureOffset") == 0)
2343                     arg = 2;
2344                 else if (fnCandidate.getName().compare("texelFetchOffset") == 0)
2345                     arg = 3;
2346                 else if (fnCandidate.getName().compare("textureProjOffset") == 0)
2347                     arg = 2;
2348                 else if (fnCandidate.getName().compare("textureLodOffset") == 0)
2349                     arg = 3;
2350                 else if (fnCandidate.getName().compare("textureProjLodOffset") == 0)
2351                     arg = 3;
2352                 else if (fnCandidate.getName().compare("textureGradOffset") == 0)
2353                     arg = 4;
2354                 else if (fnCandidate.getName().compare("textureProjGradOffset") == 0)
2355                     arg = 4;
2356 
2357                 if (arg > 0) {
2358                     if (! callNode.getSequence()[arg]->getAsConstantUnion())
2359                         error(loc, "argument must be compile-time constant", "texel offset", "");
2360                     else {
2361                         const TType& type = callNode.getSequence()[arg]->getAsTyped()->getType();
2362                         for (int c = 0; c < type.getVectorSize(); ++c) {
2363                             int offset = callNode.getSequence()[arg]->getAsConstantUnion()->getConstArray()[c].getIConst();
2364                             if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset)
2365                                 error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
2366                         }
2367                     }
2368                 }
2369             }
2370         }
2371     }
2372 
2373     // GL_ARB_shader_texture_image_samples
2374     if (fnCandidate.getName().compare(0, 14, "textureSamples") == 0 || fnCandidate.getName().compare(0, 12, "imageSamples") == 0)
2375         profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples");
2376 
2377     if (fnCandidate.getName().compare(0, 11, "imageAtomic") == 0) {
2378         const TType& imageType = callNode.getSequence()[0]->getAsTyped()->getType();
2379         if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) {
2380             if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui)
2381                 error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), "");
2382         } else {
2383             if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0)
2384                 error(loc, "only supported on integer images", fnCandidate.getName().c_str(), "");
2385             else if (imageType.getQualifier().getFormat() != ElfR32f && isEsProfile())
2386                 error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), "");
2387         }
2388     }
2389 }
2390 
2391 #endif
2392 
2393 //
2394 // Do any extra checking for a user function call.
2395 //
userFunctionCallCheck(const TSourceLoc & loc,TIntermAggregate & callNode)2396 void TParseContext::userFunctionCallCheck(const TSourceLoc& loc, TIntermAggregate& callNode)
2397 {
2398     TIntermSequence& arguments = callNode.getSequence();
2399 
2400     for (int i = 0; i < (int)arguments.size(); ++i)
2401         samplerConstructorLocationCheck(loc, "call argument", arguments[i]);
2402 }
2403 
2404 //
2405 // Emit an error if this is a sampler constructor
2406 //
samplerConstructorLocationCheck(const TSourceLoc & loc,const char * token,TIntermNode * node)2407 void TParseContext::samplerConstructorLocationCheck(const TSourceLoc& loc, const char* token, TIntermNode* node)
2408 {
2409     if (node->getAsOperator() && node->getAsOperator()->getOp() == EOpConstructTextureSampler)
2410         error(loc, "sampler constructor must appear at point of use", token, "");
2411 }
2412 
2413 //
2414 // Handle seeing a built-in constructor in a grammar production.
2415 //
handleConstructorCall(const TSourceLoc & loc,const TPublicType & publicType)2416 TFunction* TParseContext::handleConstructorCall(const TSourceLoc& loc, const TPublicType& publicType)
2417 {
2418     TType type(publicType);
2419     type.getQualifier().precision = EpqNone;
2420 
2421     if (type.isArray()) {
2422         profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed constructor");
2423         profileRequires(loc, EEsProfile, 300, nullptr, "arrayed constructor");
2424     }
2425 
2426     TOperator op = intermediate.mapTypeToConstructorOp(type);
2427 
2428     if (op == EOpNull) {
2429         error(loc, "cannot construct this type", type.getBasicString(), "");
2430         op = EOpConstructFloat;
2431         TType errorType(EbtFloat);
2432         type.shallowCopy(errorType);
2433     }
2434 
2435     TString empty("");
2436 
2437     return new TFunction(&empty, type, op);
2438 }
2439 
2440 // Handle seeing a precision qualifier in the grammar.
handlePrecisionQualifier(const TSourceLoc &,TQualifier & qualifier,TPrecisionQualifier precision)2441 void TParseContext::handlePrecisionQualifier(const TSourceLoc& /*loc*/, TQualifier& qualifier, TPrecisionQualifier precision)
2442 {
2443     if (obeyPrecisionQualifiers())
2444         qualifier.precision = precision;
2445 }
2446 
2447 // Check for messages to give on seeing a precision qualifier used in a
2448 // declaration in the grammar.
checkPrecisionQualifier(const TSourceLoc & loc,TPrecisionQualifier)2449 void TParseContext::checkPrecisionQualifier(const TSourceLoc& loc, TPrecisionQualifier)
2450 {
2451     if (precisionManager.shouldWarnAboutDefaults()) {
2452         warn(loc, "all default precisions are highp; use precision statements to quiet warning, e.g.:\n"
2453                   "         \"precision mediump int; precision highp float;\"", "", "");
2454         precisionManager.defaultWarningGiven();
2455     }
2456 }
2457 
2458 //
2459 // Same error message for all places assignments don't work.
2460 //
assignError(const TSourceLoc & loc,const char * op,TString left,TString right)2461 void TParseContext::assignError(const TSourceLoc& loc, const char* op, TString left, TString right)
2462 {
2463     error(loc, "", op, "cannot convert from '%s' to '%s'",
2464           right.c_str(), left.c_str());
2465 }
2466 
2467 //
2468 // Same error message for all places unary operations don't work.
2469 //
unaryOpError(const TSourceLoc & loc,const char * op,TString operand)2470 void TParseContext::unaryOpError(const TSourceLoc& loc, const char* op, TString operand)
2471 {
2472    error(loc, " wrong operand type", op,
2473           "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)",
2474           op, operand.c_str());
2475 }
2476 
2477 //
2478 // Same error message for all binary operations don't work.
2479 //
binaryOpError(const TSourceLoc & loc,const char * op,TString left,TString right)2480 void TParseContext::binaryOpError(const TSourceLoc& loc, const char* op, TString left, TString right)
2481 {
2482     error(loc, " wrong operand types:", op,
2483             "no operation '%s' exists that takes a left-hand operand of type '%s' and "
2484             "a right operand of type '%s' (or there is no acceptable conversion)",
2485             op, left.c_str(), right.c_str());
2486 }
2487 
2488 //
2489 // A basic type of EbtVoid is a key that the name string was seen in the source, but
2490 // it was not found as a variable in the symbol table.  If so, give the error
2491 // message and insert a dummy variable in the symbol table to prevent future errors.
2492 //
variableCheck(TIntermTyped * & nodePtr)2493 void TParseContext::variableCheck(TIntermTyped*& nodePtr)
2494 {
2495     TIntermSymbol* symbol = nodePtr->getAsSymbolNode();
2496     if (! symbol)
2497         return;
2498 
2499     if (symbol->getType().getBasicType() == EbtVoid) {
2500         const char *extraInfoFormat = "";
2501         if (spvVersion.vulkan != 0 && symbol->getName() == "gl_VertexID") {
2502           extraInfoFormat = "(Did you mean gl_VertexIndex?)";
2503         } else if (spvVersion.vulkan != 0 && symbol->getName() == "gl_InstanceID") {
2504           extraInfoFormat = "(Did you mean gl_InstanceIndex?)";
2505         }
2506         error(symbol->getLoc(), "undeclared identifier", symbol->getName().c_str(), extraInfoFormat);
2507 
2508         // Add to symbol table to prevent future error messages on the same name
2509         if (symbol->getName().size() > 0) {
2510             TVariable* fakeVariable = new TVariable(&symbol->getName(), TType(EbtFloat));
2511             symbolTable.insert(*fakeVariable);
2512 
2513             // substitute a symbol node for this new variable
2514             nodePtr = intermediate.addSymbol(*fakeVariable, symbol->getLoc());
2515         }
2516     } else {
2517         switch (symbol->getQualifier().storage) {
2518         case EvqPointCoord:
2519             profileRequires(symbol->getLoc(), ENoProfile, 120, nullptr, "gl_PointCoord");
2520             break;
2521         default: break; // some compilers want this
2522         }
2523     }
2524 }
2525 
2526 //
2527 // Both test and if necessary, spit out an error, to see if the node is really
2528 // an l-value that can be operated on this way.
2529 //
2530 // Returns true if there was an error.
2531 //
lValueErrorCheck(const TSourceLoc & loc,const char * op,TIntermTyped * node)2532 bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
2533 {
2534     TIntermBinary* binaryNode = node->getAsBinaryNode();
2535 
2536     if (binaryNode) {
2537         bool errorReturn = false;
2538 
2539         switch(binaryNode->getOp()) {
2540 #ifndef GLSLANG_WEB
2541         case EOpIndexDirect:
2542         case EOpIndexIndirect:
2543             // ...  tessellation control shader ...
2544             // If a per-vertex output variable is used as an l-value, it is a
2545             // compile-time or link-time error if the expression indicating the
2546             // vertex index is not the identifier gl_InvocationID.
2547             if (language == EShLangTessControl) {
2548                 const TType& leftType = binaryNode->getLeft()->getType();
2549                 if (leftType.getQualifier().storage == EvqVaryingOut && ! leftType.getQualifier().patch && binaryNode->getLeft()->getAsSymbolNode()) {
2550                     // we have a per-vertex output
2551                     const TIntermSymbol* rightSymbol = binaryNode->getRight()->getAsSymbolNode();
2552                     if (! rightSymbol || rightSymbol->getQualifier().builtIn != EbvInvocationId)
2553                         error(loc, "tessellation-control per-vertex output l-value must be indexed with gl_InvocationID", "[]", "");
2554                 }
2555             }
2556             break; // left node is checked by base class
2557 #endif
2558         case EOpVectorSwizzle:
2559             errorReturn = lValueErrorCheck(loc, op, binaryNode->getLeft());
2560             if (!errorReturn) {
2561                 int offset[4] = {0,0,0,0};
2562 
2563                 TIntermTyped* rightNode = binaryNode->getRight();
2564                 TIntermAggregate *aggrNode = rightNode->getAsAggregate();
2565 
2566                 for (TIntermSequence::iterator p = aggrNode->getSequence().begin();
2567                                                p != aggrNode->getSequence().end(); p++) {
2568                     int value = (*p)->getAsTyped()->getAsConstantUnion()->getConstArray()[0].getIConst();
2569                     offset[value]++;
2570                     if (offset[value] > 1) {
2571                         error(loc, " l-value of swizzle cannot have duplicate components", op, "", "");
2572 
2573                         return true;
2574                     }
2575                 }
2576             }
2577 
2578             return errorReturn;
2579         default:
2580             break;
2581         }
2582 
2583         if (errorReturn) {
2584             error(loc, " l-value required", op, "", "");
2585             return true;
2586         }
2587     }
2588 
2589     if (binaryNode && binaryNode->getOp() == EOpIndexDirectStruct && binaryNode->getLeft()->isReference())
2590         return false;
2591 
2592     // Let the base class check errors
2593     if (TParseContextBase::lValueErrorCheck(loc, op, node))
2594         return true;
2595 
2596     const char* symbol = nullptr;
2597     TIntermSymbol* symNode = node->getAsSymbolNode();
2598     if (symNode != nullptr)
2599         symbol = symNode->getName().c_str();
2600 
2601     const char* message = nullptr;
2602     switch (node->getQualifier().storage) {
2603     case EvqVaryingIn:      message = "can't modify shader input";   break;
2604     case EvqInstanceId:     message = "can't modify gl_InstanceID";  break;
2605     case EvqVertexId:       message = "can't modify gl_VertexID";    break;
2606     case EvqFace:           message = "can't modify gl_FrontFace";   break;
2607     case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
2608     case EvqPointCoord:     message = "can't modify gl_PointCoord";  break;
2609     case EvqFragDepth:
2610         intermediate.setDepthReplacing();
2611         // "In addition, it is an error to statically write to gl_FragDepth in the fragment shader."
2612         if (isEsProfile() && intermediate.getEarlyFragmentTests())
2613             message = "can't modify gl_FragDepth if using early_fragment_tests";
2614         break;
2615 
2616     default:
2617         break;
2618     }
2619 
2620     if (message == nullptr && binaryNode == nullptr && symNode == nullptr) {
2621         error(loc, " l-value required", op, "", "");
2622 
2623         return true;
2624     }
2625 
2626     //
2627     // Everything else is okay, no error.
2628     //
2629     if (message == nullptr)
2630         return false;
2631 
2632     //
2633     // If we get here, we have an error and a message.
2634     //
2635     if (symNode)
2636         error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
2637     else
2638         error(loc, " l-value required", op, "(%s)", message);
2639 
2640     return true;
2641 }
2642 
2643 // Test for and give an error if the node can't be read from.
rValueErrorCheck(const TSourceLoc & loc,const char * op,TIntermTyped * node)2644 void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
2645 {
2646     // Let the base class check errors
2647     TParseContextBase::rValueErrorCheck(loc, op, node);
2648 
2649     TIntermSymbol* symNode = node->getAsSymbolNode();
2650     if (!(symNode && symNode->getQualifier().isWriteOnly())) // base class checks
2651         if (symNode && symNode->getQualifier().isExplicitInterpolation())
2652             error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str());
2653 }
2654 
2655 //
2656 // Both test, and if necessary spit out an error, to see if the node is really
2657 // a constant.
2658 //
constantValueCheck(TIntermTyped * node,const char * token)2659 void TParseContext::constantValueCheck(TIntermTyped* node, const char* token)
2660 {
2661     if (! node->getQualifier().isConstant())
2662         error(node->getLoc(), "constant expression required", token, "");
2663 }
2664 
2665 //
2666 // Both test, and if necessary spit out an error, to see if the node is really
2667 // an integer.
2668 //
integerCheck(const TIntermTyped * node,const char * token)2669 void TParseContext::integerCheck(const TIntermTyped* node, const char* token)
2670 {
2671     if ((node->getBasicType() == EbtInt || node->getBasicType() == EbtUint) && node->isScalar())
2672         return;
2673 
2674     error(node->getLoc(), "scalar integer expression required", token, "");
2675 }
2676 
2677 //
2678 // Both test, and if necessary spit out an error, to see if we are currently
2679 // globally scoped.
2680 //
globalCheck(const TSourceLoc & loc,const char * token)2681 void TParseContext::globalCheck(const TSourceLoc& loc, const char* token)
2682 {
2683     if (! symbolTable.atGlobalLevel())
2684         error(loc, "not allowed in nested scope", token, "");
2685 }
2686 
2687 //
2688 // Reserved errors for GLSL.
2689 //
reservedErrorCheck(const TSourceLoc & loc,const TString & identifier)2690 void TParseContext::reservedErrorCheck(const TSourceLoc& loc, const TString& identifier)
2691 {
2692     // "Identifiers starting with "gl_" are reserved for use by OpenGL, and may not be
2693     // declared in a shader; this results in a compile-time error."
2694     if (! symbolTable.atBuiltInLevel()) {
2695         if (builtInName(identifier))
2696             error(loc, "identifiers starting with \"gl_\" are reserved", identifier.c_str(), "");
2697 
2698         // "__" are not supposed to be an error.  ES 300 (and desktop) added the clarification:
2699         // "In addition, all identifiers containing two consecutive underscores (__) are
2700         // reserved; using such a name does not itself result in an error, but may result
2701         // in undefined behavior."
2702         // however, before that, ES tests required an error.
2703         if (identifier.find("__") != TString::npos) {
2704             if (isEsProfile() && version < 300)
2705                 error(loc, "identifiers containing consecutive underscores (\"__\") are reserved, and an error if version < 300", identifier.c_str(), "");
2706             else
2707                 warn(loc, "identifiers containing consecutive underscores (\"__\") are reserved", identifier.c_str(), "");
2708         }
2709     }
2710 }
2711 
2712 //
2713 // Reserved errors for the preprocessor.
2714 //
reservedPpErrorCheck(const TSourceLoc & loc,const char * identifier,const char * op)2715 void TParseContext::reservedPpErrorCheck(const TSourceLoc& loc, const char* identifier, const char* op)
2716 {
2717     // "__" are not supposed to be an error.  ES 300 (and desktop) added the clarification:
2718     // "All macro names containing two consecutive underscores ( __ ) are reserved;
2719     // defining such a name does not itself result in an error, but may result in
2720     // undefined behavior.  All macro names prefixed with "GL_" ("GL" followed by a
2721     // single underscore) are also reserved, and defining such a name results in a
2722     // compile-time error."
2723     // however, before that, ES tests required an error.
2724     if (strncmp(identifier, "GL_", 3) == 0)
2725         ppError(loc, "names beginning with \"GL_\" can't be (un)defined:", op,  identifier);
2726     else if (strncmp(identifier, "defined", 8) == 0)
2727         ppError(loc, "\"defined\" can't be (un)defined:", op,  identifier);
2728     else if (strstr(identifier, "__") != 0) {
2729         if (isEsProfile() && version >= 300 &&
2730             (strcmp(identifier, "__LINE__") == 0 ||
2731              strcmp(identifier, "__FILE__") == 0 ||
2732              strcmp(identifier, "__VERSION__") == 0))
2733             ppError(loc, "predefined names can't be (un)defined:", op,  identifier);
2734         else {
2735             if (isEsProfile() && version < 300)
2736                 ppError(loc, "names containing consecutive underscores are reserved, and an error if version < 300:", op, identifier);
2737             else
2738                 ppWarn(loc, "names containing consecutive underscores are reserved:", op, identifier);
2739         }
2740     }
2741 }
2742 
2743 //
2744 // See if this version/profile allows use of the line-continuation character '\'.
2745 //
2746 // Returns true if a line continuation should be done.
2747 //
lineContinuationCheck(const TSourceLoc & loc,bool endOfComment)2748 bool TParseContext::lineContinuationCheck(const TSourceLoc& loc, bool endOfComment)
2749 {
2750 #ifdef GLSLANG_WEB
2751     return true;
2752 #endif
2753 
2754     const char* message = "line continuation";
2755 
2756     bool lineContinuationAllowed = (isEsProfile() && version >= 300) ||
2757                                    (!isEsProfile() && (version >= 420 || extensionTurnedOn(E_GL_ARB_shading_language_420pack)));
2758 
2759     if (endOfComment) {
2760         if (lineContinuationAllowed)
2761             warn(loc, "used at end of comment; the following line is still part of the comment", message, "");
2762         else
2763             warn(loc, "used at end of comment, but this version does not provide line continuation", message, "");
2764 
2765         return lineContinuationAllowed;
2766     }
2767 
2768     if (relaxedErrors()) {
2769         if (! lineContinuationAllowed)
2770             warn(loc, "not allowed in this version", message, "");
2771         return true;
2772     } else {
2773         profileRequires(loc, EEsProfile, 300, nullptr, message);
2774         profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, message);
2775     }
2776 
2777     return lineContinuationAllowed;
2778 }
2779 
builtInName(const TString & identifier)2780 bool TParseContext::builtInName(const TString& identifier)
2781 {
2782     return identifier.compare(0, 3, "gl_") == 0;
2783 }
2784 
2785 //
2786 // Make sure there is enough data and not too many arguments provided to the
2787 // constructor to build something of the type of the constructor.  Also returns
2788 // the type of the constructor.
2789 //
2790 // Part of establishing type is establishing specialization-constness.
2791 // We don't yet know "top down" whether type is a specialization constant,
2792 // but a const constructor can becomes a specialization constant if any of
2793 // its children are, subject to KHR_vulkan_glsl rules:
2794 //
2795 //     - int(), uint(), and bool() constructors for type conversions
2796 //       from any of the following types to any of the following types:
2797 //         * int
2798 //         * uint
2799 //         * bool
2800 //     - vector versions of the above conversion constructors
2801 //
2802 // Returns true if there was an error in construction.
2803 //
constructorError(const TSourceLoc & loc,TIntermNode * node,TFunction & function,TOperator op,TType & type)2804 bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, TFunction& function, TOperator op, TType& type)
2805 {
2806     // See if the constructor does not establish the main type, only requalifies
2807     // it, in which case the type comes from the argument instead of from the
2808     // constructor function.
2809     switch (op) {
2810 #ifndef GLSLANG_WEB
2811     case EOpConstructNonuniform:
2812         if (node != nullptr && node->getAsTyped() != nullptr) {
2813             type.shallowCopy(node->getAsTyped()->getType());
2814             type.getQualifier().makeTemporary();
2815             type.getQualifier().nonUniform = true;
2816         }
2817         break;
2818 #endif
2819     default:
2820         type.shallowCopy(function.getType());
2821         break;
2822     }
2823 
2824     // See if it's a matrix
2825     bool constructingMatrix = false;
2826     switch (op) {
2827     case EOpConstructTextureSampler:
2828         return constructorTextureSamplerError(loc, function);
2829     case EOpConstructMat2x2:
2830     case EOpConstructMat2x3:
2831     case EOpConstructMat2x4:
2832     case EOpConstructMat3x2:
2833     case EOpConstructMat3x3:
2834     case EOpConstructMat3x4:
2835     case EOpConstructMat4x2:
2836     case EOpConstructMat4x3:
2837     case EOpConstructMat4x4:
2838 #ifndef GLSLANG_WEB
2839     case EOpConstructDMat2x2:
2840     case EOpConstructDMat2x3:
2841     case EOpConstructDMat2x4:
2842     case EOpConstructDMat3x2:
2843     case EOpConstructDMat3x3:
2844     case EOpConstructDMat3x4:
2845     case EOpConstructDMat4x2:
2846     case EOpConstructDMat4x3:
2847     case EOpConstructDMat4x4:
2848     case EOpConstructF16Mat2x2:
2849     case EOpConstructF16Mat2x3:
2850     case EOpConstructF16Mat2x4:
2851     case EOpConstructF16Mat3x2:
2852     case EOpConstructF16Mat3x3:
2853     case EOpConstructF16Mat3x4:
2854     case EOpConstructF16Mat4x2:
2855     case EOpConstructF16Mat4x3:
2856     case EOpConstructF16Mat4x4:
2857 #endif
2858         constructingMatrix = true;
2859         break;
2860     default:
2861         break;
2862     }
2863 
2864     //
2865     // Walk the arguments for first-pass checks and collection of information.
2866     //
2867 
2868     int size = 0;
2869     bool constType = true;
2870     bool specConstType = false;   // value is only valid if constType is true
2871     bool full = false;
2872     bool overFull = false;
2873     bool matrixInMatrix = false;
2874     bool arrayArg = false;
2875     bool floatArgument = false;
2876     for (int arg = 0; arg < function.getParamCount(); ++arg) {
2877         if (function[arg].type->isArray()) {
2878             if (function[arg].type->isUnsizedArray()) {
2879                 // Can't construct from an unsized array.
2880                 error(loc, "array argument must be sized", "constructor", "");
2881                 return true;
2882             }
2883             arrayArg = true;
2884         }
2885         if (constructingMatrix && function[arg].type->isMatrix())
2886             matrixInMatrix = true;
2887 
2888         // 'full' will go to true when enough args have been seen.  If we loop
2889         // again, there is an extra argument.
2890         if (full) {
2891             // For vectors and matrices, it's okay to have too many components
2892             // available, but not okay to have unused arguments.
2893             overFull = true;
2894         }
2895 
2896         size += function[arg].type->computeNumComponents();
2897         if (op != EOpConstructStruct && ! type.isArray() && size >= type.computeNumComponents())
2898             full = true;
2899 
2900         if (! function[arg].type->getQualifier().isConstant())
2901             constType = false;
2902         if (function[arg].type->getQualifier().isSpecConstant())
2903             specConstType = true;
2904         if (function[arg].type->isFloatingDomain())
2905             floatArgument = true;
2906         if (type.isStruct()) {
2907             if (function[arg].type->contains16BitFloat()) {
2908                 requireFloat16Arithmetic(loc, "constructor", "can't construct structure containing 16-bit type");
2909             }
2910             if (function[arg].type->contains16BitInt()) {
2911                 requireInt16Arithmetic(loc, "constructor", "can't construct structure containing 16-bit type");
2912             }
2913             if (function[arg].type->contains8BitInt()) {
2914                 requireInt8Arithmetic(loc, "constructor", "can't construct structure containing 8-bit type");
2915             }
2916         }
2917     }
2918     if (op == EOpConstructNonuniform)
2919         constType = false;
2920 
2921 #ifndef GLSLANG_WEB
2922     switch (op) {
2923     case EOpConstructFloat16:
2924     case EOpConstructF16Vec2:
2925     case EOpConstructF16Vec3:
2926     case EOpConstructF16Vec4:
2927         if (type.isArray())
2928             requireFloat16Arithmetic(loc, "constructor", "16-bit arrays not supported");
2929         if (type.isVector() && function.getParamCount() != 1)
2930             requireFloat16Arithmetic(loc, "constructor", "16-bit vectors only take vector types");
2931         break;
2932     case EOpConstructUint16:
2933     case EOpConstructU16Vec2:
2934     case EOpConstructU16Vec3:
2935     case EOpConstructU16Vec4:
2936     case EOpConstructInt16:
2937     case EOpConstructI16Vec2:
2938     case EOpConstructI16Vec3:
2939     case EOpConstructI16Vec4:
2940         if (type.isArray())
2941             requireInt16Arithmetic(loc, "constructor", "16-bit arrays not supported");
2942         if (type.isVector() && function.getParamCount() != 1)
2943             requireInt16Arithmetic(loc, "constructor", "16-bit vectors only take vector types");
2944         break;
2945     case EOpConstructUint8:
2946     case EOpConstructU8Vec2:
2947     case EOpConstructU8Vec3:
2948     case EOpConstructU8Vec4:
2949     case EOpConstructInt8:
2950     case EOpConstructI8Vec2:
2951     case EOpConstructI8Vec3:
2952     case EOpConstructI8Vec4:
2953         if (type.isArray())
2954             requireInt8Arithmetic(loc, "constructor", "8-bit arrays not supported");
2955         if (type.isVector() && function.getParamCount() != 1)
2956             requireInt8Arithmetic(loc, "constructor", "8-bit vectors only take vector types");
2957         break;
2958     default:
2959         break;
2960     }
2961 #endif
2962 
2963     // inherit constness from children
2964     if (constType) {
2965         bool makeSpecConst;
2966         // Finish pinning down spec-const semantics
2967         if (specConstType) {
2968             switch (op) {
2969             case EOpConstructInt8:
2970             case EOpConstructInt:
2971             case EOpConstructUint:
2972             case EOpConstructBool:
2973             case EOpConstructBVec2:
2974             case EOpConstructBVec3:
2975             case EOpConstructBVec4:
2976             case EOpConstructIVec2:
2977             case EOpConstructIVec3:
2978             case EOpConstructIVec4:
2979             case EOpConstructUVec2:
2980             case EOpConstructUVec3:
2981             case EOpConstructUVec4:
2982 #ifndef GLSLANG_WEB
2983             case EOpConstructUint8:
2984             case EOpConstructInt16:
2985             case EOpConstructUint16:
2986             case EOpConstructInt64:
2987             case EOpConstructUint64:
2988             case EOpConstructI8Vec2:
2989             case EOpConstructI8Vec3:
2990             case EOpConstructI8Vec4:
2991             case EOpConstructU8Vec2:
2992             case EOpConstructU8Vec3:
2993             case EOpConstructU8Vec4:
2994             case EOpConstructI16Vec2:
2995             case EOpConstructI16Vec3:
2996             case EOpConstructI16Vec4:
2997             case EOpConstructU16Vec2:
2998             case EOpConstructU16Vec3:
2999             case EOpConstructU16Vec4:
3000             case EOpConstructI64Vec2:
3001             case EOpConstructI64Vec3:
3002             case EOpConstructI64Vec4:
3003             case EOpConstructU64Vec2:
3004             case EOpConstructU64Vec3:
3005             case EOpConstructU64Vec4:
3006 #endif
3007                 // This was the list of valid ones, if they aren't converting from float
3008                 // and aren't making an array.
3009                 makeSpecConst = ! floatArgument && ! type.isArray();
3010                 break;
3011             default:
3012                 // anything else wasn't white-listed in the spec as a conversion
3013                 makeSpecConst = false;
3014                 break;
3015             }
3016         } else
3017             makeSpecConst = false;
3018 
3019         if (makeSpecConst)
3020             type.getQualifier().makeSpecConstant();
3021         else if (specConstType)
3022             type.getQualifier().makeTemporary();
3023         else
3024             type.getQualifier().storage = EvqConst;
3025     }
3026 
3027     if (type.isArray()) {
3028         if (function.getParamCount() == 0) {
3029             error(loc, "array constructor must have at least one argument", "constructor", "");
3030             return true;
3031         }
3032 
3033         if (type.isUnsizedArray()) {
3034             // auto adapt the constructor type to the number of arguments
3035             type.changeOuterArraySize(function.getParamCount());
3036         } else if (type.getOuterArraySize() != function.getParamCount()) {
3037             error(loc, "array constructor needs one argument per array element", "constructor", "");
3038             return true;
3039         }
3040 
3041         if (type.isArrayOfArrays()) {
3042             // Types have to match, but we're still making the type.
3043             // Finish making the type, and the comparison is done later
3044             // when checking for conversion.
3045             TArraySizes& arraySizes = *type.getArraySizes();
3046 
3047             // At least the dimensionalities have to match.
3048             if (! function[0].type->isArray() ||
3049                     arraySizes.getNumDims() != function[0].type->getArraySizes()->getNumDims() + 1) {
3050                 error(loc, "array constructor argument not correct type to construct array element", "constructor", "");
3051                 return true;
3052             }
3053 
3054             if (arraySizes.isInnerUnsized()) {
3055                 // "Arrays of arrays ..., and the size for any dimension is optional"
3056                 // That means we need to adopt (from the first argument) the other array sizes into the type.
3057                 for (int d = 1; d < arraySizes.getNumDims(); ++d) {
3058                     if (arraySizes.getDimSize(d) == UnsizedArraySize) {
3059                         arraySizes.setDimSize(d, function[0].type->getArraySizes()->getDimSize(d - 1));
3060                     }
3061                 }
3062             }
3063         }
3064     }
3065 
3066     if (arrayArg && op != EOpConstructStruct && ! type.isArrayOfArrays()) {
3067         error(loc, "constructing non-array constituent from array argument", "constructor", "");
3068         return true;
3069     }
3070 
3071     if (matrixInMatrix && ! type.isArray()) {
3072         profileRequires(loc, ENoProfile, 120, nullptr, "constructing matrix from matrix");
3073 
3074         // "If a matrix argument is given to a matrix constructor,
3075         // it is a compile-time error to have any other arguments."
3076         if (function.getParamCount() != 1)
3077             error(loc, "matrix constructed from matrix can only have one argument", "constructor", "");
3078         return false;
3079     }
3080 
3081     if (overFull) {
3082         error(loc, "too many arguments", "constructor", "");
3083         return true;
3084     }
3085 
3086     if (op == EOpConstructStruct && ! type.isArray() && (int)type.getStruct()->size() != function.getParamCount()) {
3087         error(loc, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
3088         return true;
3089     }
3090 
3091     if ((op != EOpConstructStruct && size != 1 && size < type.computeNumComponents()) ||
3092         (op == EOpConstructStruct && size < type.computeNumComponents())) {
3093         error(loc, "not enough data provided for construction", "constructor", "");
3094         return true;
3095     }
3096 
3097     if (type.isCoopMat() && function.getParamCount() != 1) {
3098         error(loc, "wrong number of arguments", "constructor", "");
3099         return true;
3100     }
3101     if (type.isCoopMat() &&
3102         !(function[0].type->isScalar() || function[0].type->isCoopMat())) {
3103         error(loc, "Cooperative matrix constructor argument must be scalar or cooperative matrix", "constructor", "");
3104         return true;
3105     }
3106 
3107     TIntermTyped* typed = node->getAsTyped();
3108     if (typed == nullptr) {
3109         error(loc, "constructor argument does not have a type", "constructor", "");
3110         return true;
3111     }
3112     if (op != EOpConstructStruct && op != EOpConstructNonuniform && typed->getBasicType() == EbtSampler) {
3113         error(loc, "cannot convert a sampler", "constructor", "");
3114         return true;
3115     }
3116     if (op != EOpConstructStruct && typed->isAtomic()) {
3117         error(loc, "cannot convert an atomic_uint", "constructor", "");
3118         return true;
3119     }
3120     if (typed->getBasicType() == EbtVoid) {
3121         error(loc, "cannot convert a void", "constructor", "");
3122         return true;
3123     }
3124 
3125     return false;
3126 }
3127 
3128 // Verify all the correct semantics for constructing a combined texture/sampler.
3129 // Return true if the semantics are incorrect.
constructorTextureSamplerError(const TSourceLoc & loc,const TFunction & function)3130 bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const TFunction& function)
3131 {
3132     TString constructorName = function.getType().getBasicTypeString();  // TODO: performance: should not be making copy; interface needs to change
3133     const char* token = constructorName.c_str();
3134 
3135     // exactly two arguments needed
3136     if (function.getParamCount() != 2) {
3137         error(loc, "sampler-constructor requires two arguments", token, "");
3138         return true;
3139     }
3140 
3141     // For now, not allowing arrayed constructors, the rest of this function
3142     // is set up to allow them, if this test is removed:
3143     if (function.getType().isArray()) {
3144         error(loc, "sampler-constructor cannot make an array of samplers", token, "");
3145         return true;
3146     }
3147 
3148     // first argument
3149     //  * the constructor's first argument must be a texture type
3150     //  * the dimensionality (1D, 2D, 3D, Cube, Rect, Buffer, MS, and Array)
3151     //    of the texture type must match that of the constructed sampler type
3152     //    (that is, the suffixes of the type of the first argument and the
3153     //    type of the constructor will be spelled the same way)
3154     if (function[0].type->getBasicType() != EbtSampler ||
3155         ! function[0].type->getSampler().isTexture() ||
3156         function[0].type->isArray()) {
3157         error(loc, "sampler-constructor first argument must be a scalar *texture* type", token, "");
3158         return true;
3159     }
3160     // simulate the first argument's impact on the result type, so it can be compared with the encapsulated operator!=()
3161     TSampler texture = function.getType().getSampler();
3162     texture.setCombined(false);
3163     texture.shadow = false;
3164     if (texture != function[0].type->getSampler()) {
3165         error(loc, "sampler-constructor first argument must be a *texture* type"
3166                    " matching the dimensionality and sampled type of the constructor", token, "");
3167         return true;
3168     }
3169 
3170     // second argument
3171     //   * the constructor's second argument must be a scalar of type
3172     //     *sampler* or *samplerShadow*
3173     if (  function[1].type->getBasicType() != EbtSampler ||
3174         ! function[1].type->getSampler().isPureSampler() ||
3175           function[1].type->isArray()) {
3176         error(loc, "sampler-constructor second argument must be a scalar sampler or samplerShadow", token, "");
3177         return true;
3178     }
3179 
3180     return false;
3181 }
3182 
3183 // Checks to see if a void variable has been declared and raise an error message for such a case
3184 //
3185 // returns true in case of an error
3186 //
voidErrorCheck(const TSourceLoc & loc,const TString & identifier,const TBasicType basicType)3187 bool TParseContext::voidErrorCheck(const TSourceLoc& loc, const TString& identifier, const TBasicType basicType)
3188 {
3189     if (basicType == EbtVoid) {
3190         error(loc, "illegal use of type 'void'", identifier.c_str(), "");
3191         return true;
3192     }
3193 
3194     return false;
3195 }
3196 
3197 // Checks to see if the node (for the expression) contains a scalar boolean expression or not
boolCheck(const TSourceLoc & loc,const TIntermTyped * type)3198 void TParseContext::boolCheck(const TSourceLoc& loc, const TIntermTyped* type)
3199 {
3200     if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
3201         error(loc, "boolean expression expected", "", "");
3202 }
3203 
3204 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not
boolCheck(const TSourceLoc & loc,const TPublicType & pType)3205 void TParseContext::boolCheck(const TSourceLoc& loc, const TPublicType& pType)
3206 {
3207     if (pType.basicType != EbtBool || pType.arraySizes || pType.matrixCols > 1 || (pType.vectorSize > 1))
3208         error(loc, "boolean expression expected", "", "");
3209 }
3210 
samplerCheck(const TSourceLoc & loc,const TType & type,const TString & identifier,TIntermTyped *)3211 void TParseContext::samplerCheck(const TSourceLoc& loc, const TType& type, const TString& identifier, TIntermTyped* /*initializer*/)
3212 {
3213     // Check that the appropriate extension is enabled if external sampler is used.
3214     // There are two extensions. The correct one must be used based on GLSL version.
3215     if (type.getBasicType() == EbtSampler && type.getSampler().isExternal()) {
3216         if (version < 300) {
3217             requireExtensions(loc, 1, &E_GL_OES_EGL_image_external, "samplerExternalOES");
3218         } else {
3219             requireExtensions(loc, 1, &E_GL_OES_EGL_image_external_essl3, "samplerExternalOES");
3220         }
3221     }
3222     if (type.getSampler().isYuv()) {
3223         requireExtensions(loc, 1, &E_GL_EXT_YUV_target, "__samplerExternal2DY2YEXT");
3224     }
3225 
3226     if (type.getQualifier().storage == EvqUniform)
3227         return;
3228 
3229     if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtSampler))
3230         error(loc, "non-uniform struct contains a sampler or image:", type.getBasicTypeString().c_str(), identifier.c_str());
3231     else if (type.getBasicType() == EbtSampler && type.getQualifier().storage != EvqUniform) {
3232         // non-uniform sampler
3233         // not yet:  okay if it has an initializer
3234         // if (! initializer)
3235         error(loc, "sampler/image types can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
3236     }
3237 }
3238 
3239 #ifndef GLSLANG_WEB
3240 
atomicUintCheck(const TSourceLoc & loc,const TType & type,const TString & identifier)3241 void TParseContext::atomicUintCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
3242 {
3243     if (type.getQualifier().storage == EvqUniform)
3244         return;
3245 
3246     if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAtomicUint))
3247         error(loc, "non-uniform struct contains an atomic_uint:", type.getBasicTypeString().c_str(), identifier.c_str());
3248     else if (type.getBasicType() == EbtAtomicUint && type.getQualifier().storage != EvqUniform)
3249         error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
3250 }
3251 
accStructCheck(const TSourceLoc & loc,const TType & type,const TString & identifier)3252 void TParseContext::accStructCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
3253 {
3254     if (type.getQualifier().storage == EvqUniform)
3255         return;
3256 
3257     if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAccStruct))
3258         error(loc, "non-uniform struct contains an accelerationStructureNV:", type.getBasicTypeString().c_str(), identifier.c_str());
3259     else if (type.getBasicType() == EbtAccStruct && type.getQualifier().storage != EvqUniform)
3260         error(loc, "accelerationStructureNV can only be used in uniform variables or function parameters:",
3261             type.getBasicTypeString().c_str(), identifier.c_str());
3262 
3263 }
3264 
3265 #endif // GLSLANG_WEB
3266 
transparentOpaqueCheck(const TSourceLoc & loc,const TType & type,const TString & identifier)3267 void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
3268 {
3269     if (parsingBuiltins)
3270         return;
3271 
3272     if (type.getQualifier().storage != EvqUniform)
3273         return;
3274 
3275     if (type.containsNonOpaque()) {
3276         // Vulkan doesn't allow transparent uniforms outside of blocks
3277         if (spvVersion.vulkan > 0)
3278             vulkanRemoved(loc, "non-opaque uniforms outside a block");
3279         // OpenGL wants locations on these (unless they are getting automapped)
3280         if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations())
3281             error(loc, "non-opaque uniform variables need a layout(location=L)", identifier.c_str(), "");
3282     }
3283 }
3284 
3285 //
3286 // Qualifier checks knowing the qualifier and that it is a member of a struct/block.
3287 //
memberQualifierCheck(glslang::TPublicType & publicType)3288 void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType)
3289 {
3290     globalQualifierFixCheck(publicType.loc, publicType.qualifier);
3291     checkNoShaderLayouts(publicType.loc, publicType.shaderQualifiers);
3292     if (publicType.qualifier.isNonUniform()) {
3293         error(publicType.loc, "not allowed on block or structure members", "nonuniformEXT", "");
3294         publicType.qualifier.nonUniform = false;
3295     }
3296 }
3297 
3298 //
3299 // Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level.
3300 //
globalQualifierFixCheck(const TSourceLoc & loc,TQualifier & qualifier)3301 void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier)
3302 {
3303     bool nonuniformOkay = false;
3304 
3305     // move from parameter/unknown qualifiers to pipeline in/out qualifiers
3306     switch (qualifier.storage) {
3307     case EvqIn:
3308         profileRequires(loc, ENoProfile, 130, nullptr, "in for stage inputs");
3309         profileRequires(loc, EEsProfile, 300, nullptr, "in for stage inputs");
3310         qualifier.storage = EvqVaryingIn;
3311         nonuniformOkay = true;
3312         break;
3313     case EvqOut:
3314         profileRequires(loc, ENoProfile, 130, nullptr, "out for stage outputs");
3315         profileRequires(loc, EEsProfile, 300, nullptr, "out for stage outputs");
3316         qualifier.storage = EvqVaryingOut;
3317         break;
3318     case EvqInOut:
3319         qualifier.storage = EvqVaryingIn;
3320         error(loc, "cannot use 'inout' at global scope", "", "");
3321         break;
3322     case EvqGlobal:
3323     case EvqTemporary:
3324         nonuniformOkay = true;
3325         break;
3326     default:
3327         break;
3328     }
3329 
3330     if (!nonuniformOkay && qualifier.isNonUniform())
3331         error(loc, "for non-parameter, can only apply to 'in' or no storage qualifier", "nonuniformEXT", "");
3332 
3333     invariantCheck(loc, qualifier);
3334 }
3335 
3336 //
3337 // Check a full qualifier and type (no variable yet) at global level.
3338 //
globalQualifierTypeCheck(const TSourceLoc & loc,const TQualifier & qualifier,const TPublicType & publicType)3339 void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TPublicType& publicType)
3340 {
3341     if (! symbolTable.atGlobalLevel())
3342         return;
3343 
3344     if (!(publicType.userDef && publicType.userDef->isReference())) {
3345         if (qualifier.isMemoryQualifierImageAndSSBOOnly() && ! publicType.isImage() && publicType.qualifier.storage != EvqBuffer) {
3346             error(loc, "memory qualifiers cannot be used on this type", "", "");
3347         } else if (qualifier.isMemory() && (publicType.basicType != EbtSampler) && !publicType.qualifier.isUniformOrBuffer()) {
3348             error(loc, "memory qualifiers cannot be used on this type", "", "");
3349         }
3350     }
3351 
3352     if (qualifier.storage == EvqBuffer &&
3353         publicType.basicType != EbtBlock &&
3354         !qualifier.hasBufferReference())
3355         error(loc, "buffers can be declared only as blocks", "buffer", "");
3356 
3357     if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut)
3358         return;
3359 
3360     if (publicType.shaderQualifiers.hasBlendEquation())
3361         error(loc, "can only be applied to a standalone 'out'", "blend equation", "");
3362 
3363     // now, knowing it is a shader in/out, do all the in/out semantic checks
3364 
3365     if (publicType.basicType == EbtBool && !parsingBuiltins) {
3366         error(loc, "cannot be bool", GetStorageQualifierString(qualifier.storage), "");
3367         return;
3368     }
3369 
3370     if (isTypeInt(publicType.basicType) || publicType.basicType == EbtDouble)
3371         profileRequires(loc, EEsProfile, 300, nullptr, "shader input/output");
3372 
3373     if (!qualifier.flat && !qualifier.isExplicitInterpolation() && !qualifier.isPervertexNV()) {
3374         if (isTypeInt(publicType.basicType) ||
3375             publicType.basicType == EbtDouble ||
3376             (publicType.userDef && (   publicType.userDef->containsBasicType(EbtInt)
3377                                     || publicType.userDef->containsBasicType(EbtUint)
3378                                     || publicType.userDef->contains16BitInt()
3379                                     || publicType.userDef->contains8BitInt()
3380                                     || publicType.userDef->contains64BitInt()
3381                                     || publicType.userDef->containsDouble()))) {
3382             if (qualifier.storage == EvqVaryingIn && language == EShLangFragment)
3383                 error(loc, "must be qualified as flat", TType::getBasicString(publicType.basicType), GetStorageQualifierString(qualifier.storage));
3384             else if (qualifier.storage == EvqVaryingOut && language == EShLangVertex && version == 300)
3385                 error(loc, "must be qualified as flat", TType::getBasicString(publicType.basicType), GetStorageQualifierString(qualifier.storage));
3386         }
3387     }
3388 
3389     if (qualifier.isPatch() && qualifier.isInterpolation())
3390         error(loc, "cannot use interpolation qualifiers with patch", "patch", "");
3391 
3392     if (qualifier.isTaskMemory() && publicType.basicType != EbtBlock)
3393         error(loc, "taskNV variables can be declared only as blocks", "taskNV", "");
3394 
3395     if (qualifier.storage == EvqVaryingIn) {
3396         switch (language) {
3397         case EShLangVertex:
3398             if (publicType.basicType == EbtStruct) {
3399                 error(loc, "cannot be a structure or array", GetStorageQualifierString(qualifier.storage), "");
3400                 return;
3401             }
3402             if (publicType.arraySizes) {
3403                 requireProfile(loc, ~EEsProfile, "vertex input arrays");
3404                 profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays");
3405             }
3406             if (publicType.basicType == EbtDouble)
3407                 profileRequires(loc, ~EEsProfile, 410, nullptr, "vertex-shader `double` type input");
3408             if (qualifier.isAuxiliary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant)
3409                 error(loc, "vertex input cannot be further qualified", "", "");
3410             break;
3411         case EShLangFragment:
3412             if (publicType.userDef) {
3413                 profileRequires(loc, EEsProfile, 300, nullptr, "fragment-shader struct input");
3414                 profileRequires(loc, ~EEsProfile, 150, nullptr, "fragment-shader struct input");
3415                 if (publicType.userDef->containsStructure())
3416                     requireProfile(loc, ~EEsProfile, "fragment-shader struct input containing structure");
3417                 if (publicType.userDef->containsArray())
3418                     requireProfile(loc, ~EEsProfile, "fragment-shader struct input containing an array");
3419             }
3420             break;
3421        case EShLangCompute:
3422             if (! symbolTable.atBuiltInLevel())
3423                 error(loc, "global storage input qualifier cannot be used in a compute shader", "in", "");
3424             break;
3425 #ifndef GLSLANG_WEB
3426        case EShLangTessControl:
3427             if (qualifier.patch)
3428                 error(loc, "can only use on output in tessellation-control shader", "patch", "");
3429             break;
3430 #endif
3431         default:
3432             break;
3433         }
3434     } else {
3435         // qualifier.storage == EvqVaryingOut
3436         switch (language) {
3437         case EShLangVertex:
3438             if (publicType.userDef) {
3439                 profileRequires(loc, EEsProfile, 300, nullptr, "vertex-shader struct output");
3440                 profileRequires(loc, ~EEsProfile, 150, nullptr, "vertex-shader struct output");
3441                 if (publicType.userDef->containsStructure())
3442                     requireProfile(loc, ~EEsProfile, "vertex-shader struct output containing structure");
3443                 if (publicType.userDef->containsArray())
3444                     requireProfile(loc, ~EEsProfile, "vertex-shader struct output containing an array");
3445             }
3446 
3447             break;
3448         case EShLangFragment:
3449             profileRequires(loc, EEsProfile, 300, nullptr, "fragment shader output");
3450             if (publicType.basicType == EbtStruct) {
3451                 error(loc, "cannot be a structure", GetStorageQualifierString(qualifier.storage), "");
3452                 return;
3453             }
3454             if (publicType.matrixRows > 0) {
3455                 error(loc, "cannot be a matrix", GetStorageQualifierString(qualifier.storage), "");
3456                 return;
3457             }
3458             if (qualifier.isAuxiliary())
3459                 error(loc, "can't use auxiliary qualifier on a fragment output", "centroid/sample/patch", "");
3460             if (qualifier.isInterpolation())
3461                 error(loc, "can't use interpolation qualifier on a fragment output", "flat/smooth/noperspective", "");
3462             if (publicType.basicType == EbtDouble || publicType.basicType == EbtInt64 || publicType.basicType == EbtUint64)
3463                 error(loc, "cannot contain a double, int64, or uint64", GetStorageQualifierString(qualifier.storage), "");
3464         break;
3465 
3466         case EShLangCompute:
3467             error(loc, "global storage output qualifier cannot be used in a compute shader", "out", "");
3468             break;
3469 #ifndef GLSLANG_WEB
3470         case EShLangTessEvaluation:
3471             if (qualifier.patch)
3472                 error(loc, "can only use on input in tessellation-evaluation shader", "patch", "");
3473             break;
3474 #endif
3475         default:
3476             break;
3477         }
3478     }
3479 }
3480 
3481 //
3482 // Merge characteristics of the 'src' qualifier into the 'dst'.
3483 // If there is duplication, issue error messages, unless 'force'
3484 // is specified, which means to just override default settings.
3485 //
3486 // Also, when force is false, it will be assumed that 'src' follows
3487 // 'dst', for the purpose of error checking order for versions
3488 // that require specific orderings of qualifiers.
3489 //
mergeQualifiers(const TSourceLoc & loc,TQualifier & dst,const TQualifier & src,bool force)3490 void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, const TQualifier& src, bool force)
3491 {
3492     // Multiple auxiliary qualifiers (mostly done later by 'individual qualifiers')
3493     if (src.isAuxiliary() && dst.isAuxiliary())
3494         error(loc, "can only have one auxiliary qualifier (centroid, patch, and sample)", "", "");
3495 
3496     // Multiple interpolation qualifiers (mostly done later by 'individual qualifiers')
3497     if (src.isInterpolation() && dst.isInterpolation())
3498         error(loc, "can only have one interpolation qualifier (flat, smooth, noperspective, __explicitInterpAMD)", "", "");
3499 
3500     // Ordering
3501     if (! force && ((!isEsProfile() && version < 420) ||
3502                     (isEsProfile() && version < 310))
3503                 && ! extensionTurnedOn(E_GL_ARB_shading_language_420pack)) {
3504         // non-function parameters
3505         if (src.isNoContraction() && (dst.invariant || dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone))
3506             error(loc, "precise qualifier must appear first", "", "");
3507         if (src.invariant && (dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone))
3508             error(loc, "invariant qualifier must appear before interpolation, storage, and precision qualifiers ", "", "");
3509         else if (src.isInterpolation() && (dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone))
3510             error(loc, "interpolation qualifiers must appear before storage and precision qualifiers", "", "");
3511         else if (src.isAuxiliary() && (dst.storage != EvqTemporary || dst.precision != EpqNone))
3512             error(loc, "Auxiliary qualifiers (centroid, patch, and sample) must appear before storage and precision qualifiers", "", "");
3513         else if (src.storage != EvqTemporary && (dst.precision != EpqNone))
3514             error(loc, "precision qualifier must appear as last qualifier", "", "");
3515 
3516         // function parameters
3517         if (src.isNoContraction() && (dst.storage == EvqConst || dst.storage == EvqIn || dst.storage == EvqOut))
3518             error(loc, "precise qualifier must appear first", "", "");
3519         if (src.storage == EvqConst && (dst.storage == EvqIn || dst.storage == EvqOut))
3520             error(loc, "in/out must appear before const", "", "");
3521     }
3522 
3523     // Storage qualification
3524     if (dst.storage == EvqTemporary || dst.storage == EvqGlobal)
3525         dst.storage = src.storage;
3526     else if ((dst.storage == EvqIn  && src.storage == EvqOut) ||
3527              (dst.storage == EvqOut && src.storage == EvqIn))
3528         dst.storage = EvqInOut;
3529     else if ((dst.storage == EvqIn    && src.storage == EvqConst) ||
3530              (dst.storage == EvqConst && src.storage == EvqIn))
3531         dst.storage = EvqConstReadOnly;
3532     else if (src.storage != EvqTemporary &&
3533              src.storage != EvqGlobal)
3534         error(loc, "too many storage qualifiers", GetStorageQualifierString(src.storage), "");
3535 
3536     // Precision qualifiers
3537     if (! force && src.precision != EpqNone && dst.precision != EpqNone)
3538         error(loc, "only one precision qualifier allowed", GetPrecisionQualifierString(src.precision), "");
3539     if (dst.precision == EpqNone || (force && src.precision != EpqNone))
3540         dst.precision = src.precision;
3541 
3542 #ifndef GLSLANG_WEB
3543     if (!force && ((src.coherent && (dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
3544                    (src.devicecoherent && (dst.coherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
3545                    (src.queuefamilycoherent && (dst.coherent || dst.devicecoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
3546                    (src.workgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
3547                    (src.subgroupcoherent  && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.shadercallcoherent)) ||
3548                    (src.shadercallcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)))) {
3549         error(loc, "only one coherent/devicecoherent/queuefamilycoherent/workgroupcoherent/subgroupcoherent/shadercallcoherent qualifier allowed",
3550             GetPrecisionQualifierString(src.precision), "");
3551     }
3552 #endif
3553     // Layout qualifiers
3554     mergeObjectLayoutQualifiers(dst, src, false);
3555 
3556     // individual qualifiers
3557     bool repeated = false;
3558     #define MERGE_SINGLETON(field) repeated |= dst.field && src.field; dst.field |= src.field;
3559     MERGE_SINGLETON(invariant);
3560     MERGE_SINGLETON(centroid);
3561     MERGE_SINGLETON(smooth);
3562     MERGE_SINGLETON(flat);
3563     MERGE_SINGLETON(specConstant);
3564 #ifndef GLSLANG_WEB
3565     MERGE_SINGLETON(noContraction);
3566     MERGE_SINGLETON(nopersp);
3567     MERGE_SINGLETON(explicitInterp);
3568     MERGE_SINGLETON(perPrimitiveNV);
3569     MERGE_SINGLETON(perViewNV);
3570     MERGE_SINGLETON(perTaskNV);
3571     MERGE_SINGLETON(patch);
3572     MERGE_SINGLETON(sample);
3573     MERGE_SINGLETON(coherent);
3574     MERGE_SINGLETON(devicecoherent);
3575     MERGE_SINGLETON(queuefamilycoherent);
3576     MERGE_SINGLETON(workgroupcoherent);
3577     MERGE_SINGLETON(subgroupcoherent);
3578     MERGE_SINGLETON(shadercallcoherent);
3579     MERGE_SINGLETON(nonprivate);
3580     MERGE_SINGLETON(volatil);
3581     MERGE_SINGLETON(restrict);
3582     MERGE_SINGLETON(readonly);
3583     MERGE_SINGLETON(writeonly);
3584     MERGE_SINGLETON(nonUniform);
3585 #endif
3586 
3587     if (repeated)
3588         error(loc, "replicated qualifiers", "", "");
3589 }
3590 
setDefaultPrecision(const TSourceLoc & loc,TPublicType & publicType,TPrecisionQualifier qualifier)3591 void TParseContext::setDefaultPrecision(const TSourceLoc& loc, TPublicType& publicType, TPrecisionQualifier qualifier)
3592 {
3593     TBasicType basicType = publicType.basicType;
3594 
3595     if (basicType == EbtSampler) {
3596         defaultSamplerPrecision[computeSamplerTypeIndex(publicType.sampler)] = qualifier;
3597 
3598         return;  // all is well
3599     }
3600 
3601     if (basicType == EbtInt || basicType == EbtFloat) {
3602         if (publicType.isScalar()) {
3603             defaultPrecision[basicType] = qualifier;
3604             if (basicType == EbtInt) {
3605                 defaultPrecision[EbtUint] = qualifier;
3606                 precisionManager.explicitIntDefaultSeen();
3607             } else
3608                 precisionManager.explicitFloatDefaultSeen();
3609 
3610             return;  // all is well
3611         }
3612     }
3613 
3614     if (basicType == EbtAtomicUint) {
3615         if (qualifier != EpqHigh)
3616             error(loc, "can only apply highp to atomic_uint", "precision", "");
3617 
3618         return;
3619     }
3620 
3621     error(loc, "cannot apply precision statement to this type; use 'float', 'int' or a sampler type", TType::getBasicString(basicType), "");
3622 }
3623 
3624 // used to flatten the sampler type space into a single dimension
3625 // correlates with the declaration of defaultSamplerPrecision[]
computeSamplerTypeIndex(TSampler & sampler)3626 int TParseContext::computeSamplerTypeIndex(TSampler& sampler)
3627 {
3628     int arrayIndex    = sampler.arrayed         ? 1 : 0;
3629     int shadowIndex   = sampler.shadow          ? 1 : 0;
3630     int externalIndex = sampler.isExternal()    ? 1 : 0;
3631     int imageIndex    = sampler.isImageClass()  ? 1 : 0;
3632     int msIndex       = sampler.isMultiSample() ? 1 : 0;
3633 
3634     int flattened = EsdNumDims * (EbtNumTypes * (2 * (2 * (2 * (2 * arrayIndex + msIndex) + imageIndex) + shadowIndex) +
3635                                                  externalIndex) + sampler.type) + sampler.dim;
3636     assert(flattened < maxSamplerIndex);
3637 
3638     return flattened;
3639 }
3640 
getDefaultPrecision(TPublicType & publicType)3641 TPrecisionQualifier TParseContext::getDefaultPrecision(TPublicType& publicType)
3642 {
3643     if (publicType.basicType == EbtSampler)
3644         return defaultSamplerPrecision[computeSamplerTypeIndex(publicType.sampler)];
3645     else
3646         return defaultPrecision[publicType.basicType];
3647 }
3648 
precisionQualifierCheck(const TSourceLoc & loc,TBasicType baseType,TQualifier & qualifier)3649 void TParseContext::precisionQualifierCheck(const TSourceLoc& loc, TBasicType baseType, TQualifier& qualifier)
3650 {
3651     // Built-in symbols are allowed some ambiguous precisions, to be pinned down
3652     // later by context.
3653     if (! obeyPrecisionQualifiers() || parsingBuiltins)
3654         return;
3655 
3656 #ifndef GLSLANG_WEB
3657     if (baseType == EbtAtomicUint && qualifier.precision != EpqNone && qualifier.precision != EpqHigh)
3658         error(loc, "atomic counters can only be highp", "atomic_uint", "");
3659 #endif
3660 
3661     if (baseType == EbtFloat || baseType == EbtUint || baseType == EbtInt || baseType == EbtSampler || baseType == EbtAtomicUint) {
3662         if (qualifier.precision == EpqNone) {
3663             if (relaxedErrors())
3664                 warn(loc, "type requires declaration of default precision qualifier", TType::getBasicString(baseType), "substituting 'mediump'");
3665             else
3666                 error(loc, "type requires declaration of default precision qualifier", TType::getBasicString(baseType), "");
3667             qualifier.precision = EpqMedium;
3668             defaultPrecision[baseType] = EpqMedium;
3669         }
3670     } else if (qualifier.precision != EpqNone)
3671         error(loc, "type cannot have precision qualifier", TType::getBasicString(baseType), "");
3672 }
3673 
parameterTypeCheck(const TSourceLoc & loc,TStorageQualifier qualifier,const TType & type)3674 void TParseContext::parameterTypeCheck(const TSourceLoc& loc, TStorageQualifier qualifier, const TType& type)
3675 {
3676     if ((qualifier == EvqOut || qualifier == EvqInOut) && type.isOpaque())
3677         error(loc, "samplers and atomic_uints cannot be output parameters", type.getBasicTypeString().c_str(), "");
3678     if (!parsingBuiltins && type.contains16BitFloat())
3679         requireFloat16Arithmetic(loc, type.getBasicTypeString().c_str(), "float16 types can only be in uniform block or buffer storage");
3680     if (!parsingBuiltins && type.contains16BitInt())
3681         requireInt16Arithmetic(loc, type.getBasicTypeString().c_str(), "(u)int16 types can only be in uniform block or buffer storage");
3682     if (!parsingBuiltins && type.contains8BitInt())
3683         requireInt8Arithmetic(loc, type.getBasicTypeString().c_str(), "(u)int8 types can only be in uniform block or buffer storage");
3684 }
3685 
containsFieldWithBasicType(const TType & type,TBasicType basicType)3686 bool TParseContext::containsFieldWithBasicType(const TType& type, TBasicType basicType)
3687 {
3688     if (type.getBasicType() == basicType)
3689         return true;
3690 
3691     if (type.getBasicType() == EbtStruct) {
3692         const TTypeList& structure = *type.getStruct();
3693         for (unsigned int i = 0; i < structure.size(); ++i) {
3694             if (containsFieldWithBasicType(*structure[i].type, basicType))
3695                 return true;
3696         }
3697     }
3698 
3699     return false;
3700 }
3701 
3702 //
3703 // Do size checking for an array type's size.
3704 //
arraySizeCheck(const TSourceLoc & loc,TIntermTyped * expr,TArraySize & sizePair,const char * sizeType)3705 void TParseContext::arraySizeCheck(const TSourceLoc& loc, TIntermTyped* expr, TArraySize& sizePair, const char *sizeType)
3706 {
3707     bool isConst = false;
3708     sizePair.node = nullptr;
3709 
3710     int size = 1;
3711 
3712     TIntermConstantUnion* constant = expr->getAsConstantUnion();
3713     if (constant) {
3714         // handle true (non-specialization) constant
3715         size = constant->getConstArray()[0].getIConst();
3716         isConst = true;
3717     } else {
3718         // see if it's a specialization constant instead
3719         if (expr->getQualifier().isSpecConstant()) {
3720             isConst = true;
3721             sizePair.node = expr;
3722             TIntermSymbol* symbol = expr->getAsSymbolNode();
3723             if (symbol && symbol->getConstArray().size() > 0)
3724                 size = symbol->getConstArray()[0].getIConst();
3725         } else if (expr->getAsUnaryNode() &&
3726                    expr->getAsUnaryNode()->getOp() == glslang::EOpArrayLength &&
3727                    expr->getAsUnaryNode()->getOperand()->getType().isCoopMat()) {
3728             isConst = true;
3729             size = 1;
3730             sizePair.node = expr->getAsUnaryNode();
3731         }
3732     }
3733 
3734     sizePair.size = size;
3735 
3736     if (! isConst || (expr->getBasicType() != EbtInt && expr->getBasicType() != EbtUint)) {
3737         error(loc, sizeType, "", "must be a constant integer expression");
3738         return;
3739     }
3740 
3741     if (size <= 0) {
3742         error(loc, sizeType, "", "must be a positive integer");
3743         return;
3744     }
3745 }
3746 
3747 //
3748 // See if this qualifier can be an array.
3749 //
3750 // Returns true if there is an error.
3751 //
arrayQualifierError(const TSourceLoc & loc,const TQualifier & qualifier)3752 bool TParseContext::arrayQualifierError(const TSourceLoc& loc, const TQualifier& qualifier)
3753 {
3754     if (qualifier.storage == EvqConst) {
3755         profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "const array");
3756         profileRequires(loc, EEsProfile, 300, nullptr, "const array");
3757     }
3758 
3759     if (qualifier.storage == EvqVaryingIn && language == EShLangVertex) {
3760         requireProfile(loc, ~EEsProfile, "vertex input arrays");
3761         profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays");
3762     }
3763 
3764     return false;
3765 }
3766 
3767 //
3768 // See if this qualifier and type combination can be an array.
3769 // Assumes arrayQualifierError() was also called to catch the type-invariant tests.
3770 //
3771 // Returns true if there is an error.
3772 //
arrayError(const TSourceLoc & loc,const TType & type)3773 bool TParseContext::arrayError(const TSourceLoc& loc, const TType& type)
3774 {
3775     if (type.getQualifier().storage == EvqVaryingOut && language == EShLangVertex) {
3776         if (type.isArrayOfArrays())
3777             requireProfile(loc, ~EEsProfile, "vertex-shader array-of-array output");
3778         else if (type.isStruct())
3779             requireProfile(loc, ~EEsProfile, "vertex-shader array-of-struct output");
3780     }
3781     if (type.getQualifier().storage == EvqVaryingIn && language == EShLangFragment) {
3782         if (type.isArrayOfArrays())
3783             requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array input");
3784         else if (type.isStruct())
3785             requireProfile(loc, ~EEsProfile, "fragment-shader array-of-struct input");
3786     }
3787     if (type.getQualifier().storage == EvqVaryingOut && language == EShLangFragment) {
3788         if (type.isArrayOfArrays())
3789             requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array output");
3790     }
3791 
3792     return false;
3793 }
3794 
3795 //
3796 // Require array to be completely sized
3797 //
arraySizeRequiredCheck(const TSourceLoc & loc,const TArraySizes & arraySizes)3798 void TParseContext::arraySizeRequiredCheck(const TSourceLoc& loc, const TArraySizes& arraySizes)
3799 {
3800     if (!parsingBuiltins && arraySizes.hasUnsized())
3801         error(loc, "array size required", "", "");
3802 }
3803 
structArrayCheck(const TSourceLoc &,const TType & type)3804 void TParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& type)
3805 {
3806     const TTypeList& structure = *type.getStruct();
3807     for (int m = 0; m < (int)structure.size(); ++m) {
3808         const TType& member = *structure[m].type;
3809         if (member.isArray())
3810             arraySizeRequiredCheck(structure[m].loc, *member.getArraySizes());
3811     }
3812 }
3813 
arraySizesCheck(const TSourceLoc & loc,const TQualifier & qualifier,TArraySizes * arraySizes,const TIntermTyped * initializer,bool lastMember)3814 void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qualifier, TArraySizes* arraySizes,
3815     const TIntermTyped* initializer, bool lastMember)
3816 {
3817     assert(arraySizes);
3818 
3819     // always allow special built-in ins/outs sized to topologies
3820     if (parsingBuiltins)
3821         return;
3822 
3823     // initializer must be a sized array, in which case
3824     // allow the initializer to set any unknown array sizes
3825     if (initializer != nullptr) {
3826         if (initializer->getType().isUnsizedArray())
3827             error(loc, "array initializer must be sized", "[]", "");
3828         return;
3829     }
3830 
3831     // No environment allows any non-outer-dimension to be implicitly sized
3832     if (arraySizes->isInnerUnsized()) {
3833         error(loc, "only outermost dimension of an array of arrays can be implicitly sized", "[]", "");
3834         arraySizes->clearInnerUnsized();
3835     }
3836 
3837     if (arraySizes->isInnerSpecialization() &&
3838         (qualifier.storage != EvqTemporary && qualifier.storage != EvqGlobal && qualifier.storage != EvqShared && qualifier.storage != EvqConst))
3839         error(loc, "only outermost dimension of an array of arrays can be a specialization constant", "[]", "");
3840 
3841 #ifndef GLSLANG_WEB
3842 
3843     // desktop always allows outer-dimension-unsized variable arrays,
3844     if (!isEsProfile())
3845         return;
3846 
3847     // for ES, if size isn't coming from an initializer, it has to be explicitly declared now,
3848     // with very few exceptions
3849 
3850     // implicitly-sized io exceptions:
3851     switch (language) {
3852     case EShLangGeometry:
3853         if (qualifier.storage == EvqVaryingIn)
3854             if ((isEsProfile() && version >= 320) ||
3855                 extensionsTurnedOn(Num_AEP_geometry_shader, AEP_geometry_shader))
3856                 return;
3857         break;
3858     case EShLangTessControl:
3859         if ( qualifier.storage == EvqVaryingIn ||
3860             (qualifier.storage == EvqVaryingOut && ! qualifier.isPatch()))
3861             if ((isEsProfile() && version >= 320) ||
3862                 extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))
3863                 return;
3864         break;
3865     case EShLangTessEvaluation:
3866         if ((qualifier.storage == EvqVaryingIn && ! qualifier.isPatch()) ||
3867              qualifier.storage == EvqVaryingOut)
3868             if ((isEsProfile() && version >= 320) ||
3869                 extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))
3870                 return;
3871         break;
3872     case EShLangMeshNV:
3873         if (qualifier.storage == EvqVaryingOut)
3874             if ((isEsProfile() && version >= 320) ||
3875                 extensionTurnedOn(E_GL_NV_mesh_shader))
3876                 return;
3877         break;
3878     default:
3879         break;
3880     }
3881 
3882 #endif
3883 
3884     // last member of ssbo block exception:
3885     if (qualifier.storage == EvqBuffer && lastMember)
3886         return;
3887 
3888     arraySizeRequiredCheck(loc, *arraySizes);
3889 }
3890 
arrayOfArrayVersionCheck(const TSourceLoc & loc,const TArraySizes * sizes)3891 void TParseContext::arrayOfArrayVersionCheck(const TSourceLoc& loc, const TArraySizes* sizes)
3892 {
3893     if (sizes == nullptr || sizes->getNumDims() == 1)
3894         return;
3895 
3896     const char* feature = "arrays of arrays";
3897 
3898     requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature);
3899     profileRequires(loc, EEsProfile, 310, nullptr, feature);
3900     profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, feature);
3901 }
3902 
3903 //
3904 // Do all the semantic checking for declaring or redeclaring an array, with and
3905 // without a size, and make the right changes to the symbol table.
3906 //
declareArray(const TSourceLoc & loc,const TString & identifier,const TType & type,TSymbol * & symbol)3907 void TParseContext::declareArray(const TSourceLoc& loc, const TString& identifier, const TType& type, TSymbol*& symbol)
3908 {
3909     if (symbol == nullptr) {
3910         bool currentScope;
3911         symbol = symbolTable.find(identifier, nullptr, &currentScope);
3912 
3913         if (symbol && builtInName(identifier) && ! symbolTable.atBuiltInLevel()) {
3914             // bad shader (errors already reported) trying to redeclare a built-in name as an array
3915             symbol = nullptr;
3916             return;
3917         }
3918         if (symbol == nullptr || ! currentScope) {
3919             //
3920             // Successfully process a new definition.
3921             // (Redeclarations have to take place at the same scope; otherwise they are hiding declarations)
3922             //
3923             symbol = new TVariable(&identifier, type);
3924             symbolTable.insert(*symbol);
3925             if (symbolTable.atGlobalLevel())
3926                 trackLinkage(*symbol);
3927 
3928 #ifndef GLSLANG_WEB
3929             if (! symbolTable.atBuiltInLevel()) {
3930                 if (isIoResizeArray(type)) {
3931                     ioArraySymbolResizeList.push_back(symbol);
3932                     checkIoArraysConsistency(loc, true);
3933                 } else
3934                     fixIoArraySize(loc, symbol->getWritableType());
3935             }
3936 #endif
3937 
3938             return;
3939         }
3940         if (symbol->getAsAnonMember()) {
3941             error(loc, "cannot redeclare a user-block member array", identifier.c_str(), "");
3942             symbol = nullptr;
3943             return;
3944         }
3945     }
3946 
3947     //
3948     // Process a redeclaration.
3949     //
3950 
3951     if (symbol == nullptr) {
3952         error(loc, "array variable name expected", identifier.c_str(), "");
3953         return;
3954     }
3955 
3956     // redeclareBuiltinVariable() should have already done the copyUp()
3957     TType& existingType = symbol->getWritableType();
3958 
3959     if (! existingType.isArray()) {
3960         error(loc, "redeclaring non-array as array", identifier.c_str(), "");
3961         return;
3962     }
3963 
3964     if (! existingType.sameElementType(type)) {
3965         error(loc, "redeclaration of array with a different element type", identifier.c_str(), "");
3966         return;
3967     }
3968 
3969     if (! existingType.sameInnerArrayness(type)) {
3970         error(loc, "redeclaration of array with a different array dimensions or sizes", identifier.c_str(), "");
3971         return;
3972     }
3973 
3974 #ifndef GLSLANG_WEB
3975     if (existingType.isSizedArray()) {
3976         // be more leniant for input arrays to geometry shaders and tessellation control outputs, where the redeclaration is the same size
3977         if (! (isIoResizeArray(type) && existingType.getOuterArraySize() == type.getOuterArraySize()))
3978             error(loc, "redeclaration of array with size", identifier.c_str(), "");
3979         return;
3980     }
3981 
3982     arrayLimitCheck(loc, identifier, type.getOuterArraySize());
3983 
3984     existingType.updateArraySizes(type);
3985 
3986     if (isIoResizeArray(type))
3987         checkIoArraysConsistency(loc);
3988 #endif
3989 }
3990 
3991 #ifndef GLSLANG_WEB
3992 
3993 // Policy and error check for needing a runtime sized array.
checkRuntimeSizable(const TSourceLoc & loc,const TIntermTyped & base)3994 void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermTyped& base)
3995 {
3996     // runtime length implies runtime sizeable, so no problem
3997     if (isRuntimeLength(base))
3998         return;
3999 
4000     // Check for last member of a bufferreference type, which is runtime sizeable
4001     // but doesn't support runtime length
4002     if (base.getType().getQualifier().storage == EvqBuffer) {
4003         const TIntermBinary* binary = base.getAsBinaryNode();
4004         if (binary != nullptr &&
4005             binary->getOp() == EOpIndexDirectStruct &&
4006             binary->getLeft()->isReference()) {
4007 
4008             const int index = binary->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
4009             const int memberCount = (int)binary->getLeft()->getType().getReferentType()->getStruct()->size();
4010             if (index == memberCount - 1)
4011                 return;
4012         }
4013     }
4014 
4015     // check for additional things allowed by GL_EXT_nonuniform_qualifier
4016     if (base.getBasicType() == EbtSampler || base.getBasicType() == EbtAccStruct || base.getBasicType() == EbtRayQuery ||
4017         (base.getBasicType() == EbtBlock && base.getType().getQualifier().isUniformOrBuffer()))
4018         requireExtensions(loc, 1, &E_GL_EXT_nonuniform_qualifier, "variable index");
4019     else
4020         error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable");
4021 }
4022 
4023 // Policy decision for whether a run-time .length() is allowed.
isRuntimeLength(const TIntermTyped & base) const4024 bool TParseContext::isRuntimeLength(const TIntermTyped& base) const
4025 {
4026     if (base.getType().getQualifier().storage == EvqBuffer) {
4027         // in a buffer block
4028         const TIntermBinary* binary = base.getAsBinaryNode();
4029         if (binary != nullptr && binary->getOp() == EOpIndexDirectStruct) {
4030             // is it the last member?
4031             const int index = binary->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
4032 
4033             if (binary->getLeft()->isReference())
4034                 return false;
4035 
4036             const int memberCount = (int)binary->getLeft()->getType().getStruct()->size();
4037             if (index == memberCount - 1)
4038                 return true;
4039         }
4040     }
4041 
4042     return false;
4043 }
4044 
4045 // Check if mesh perviewNV attributes have a view dimension
4046 // and resize it to gl_MaxMeshViewCountNV when implicitly sized.
checkAndResizeMeshViewDim(const TSourceLoc & loc,TType & type,bool isBlockMember)4047 void TParseContext::checkAndResizeMeshViewDim(const TSourceLoc& loc, TType& type, bool isBlockMember)
4048 {
4049     // see if member is a per-view attribute
4050     if (!type.getQualifier().isPerView())
4051         return;
4052 
4053     if ((isBlockMember && type.isArray()) || (!isBlockMember && type.isArrayOfArrays())) {
4054         // since we don't have the maxMeshViewCountNV set during parsing builtins, we hardcode the value.
4055         int maxViewCount = parsingBuiltins ? 4 : resources.maxMeshViewCountNV;
4056         // For block members, outermost array dimension is the view dimension.
4057         // For non-block members, outermost array dimension is the vertex/primitive dimension
4058         // and 2nd outermost is the view dimension.
4059         int viewDim = isBlockMember ? 0 : 1;
4060         int viewDimSize = type.getArraySizes()->getDimSize(viewDim);
4061 
4062         if (viewDimSize != UnsizedArraySize && viewDimSize != maxViewCount)
4063             error(loc, "mesh view output array size must be gl_MaxMeshViewCountNV or implicitly sized", "[]", "");
4064         else if (viewDimSize == UnsizedArraySize)
4065             type.getArraySizes()->setDimSize(viewDim, maxViewCount);
4066     }
4067     else {
4068         error(loc, "requires a view array dimension", "perviewNV", "");
4069     }
4070 }
4071 
4072 #endif // GLSLANG_WEB
4073 
4074 // Returns true if the first argument to the #line directive is the line number for the next line.
4075 //
4076 // Desktop, pre-version 3.30:  "After processing this directive
4077 // (including its new-line), the implementation will behave as if it is compiling at line number line+1 and
4078 // source string number source-string-number."
4079 //
4080 // Desktop, version 3.30 and later, and ES:  "After processing this directive
4081 // (including its new-line), the implementation will behave as if it is compiling at line number line and
4082 // source string number source-string-number.
lineDirectiveShouldSetNextLine() const4083 bool TParseContext::lineDirectiveShouldSetNextLine() const
4084 {
4085     return isEsProfile() || version >= 330;
4086 }
4087 
4088 //
4089 // Enforce non-initializer type/qualifier rules.
4090 //
nonInitConstCheck(const TSourceLoc & loc,TString & identifier,TType & type)4091 void TParseContext::nonInitConstCheck(const TSourceLoc& loc, TString& identifier, TType& type)
4092 {
4093     //
4094     // Make the qualifier make sense, given that there is not an initializer.
4095     //
4096     if (type.getQualifier().storage == EvqConst ||
4097         type.getQualifier().storage == EvqConstReadOnly) {
4098         type.getQualifier().makeTemporary();
4099         error(loc, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
4100     }
4101 }
4102 
4103 //
4104 // See if the identifier is a built-in symbol that can be redeclared, and if so,
4105 // copy the symbol table's read-only built-in variable to the current
4106 // global level, where it can be modified based on the passed in type.
4107 //
4108 // Returns nullptr if no redeclaration took place; meaning a normal declaration still
4109 // needs to occur for it, not necessarily an error.
4110 //
4111 // Returns a redeclared and type-modified variable if a redeclarated occurred.
4112 //
redeclareBuiltinVariable(const TSourceLoc & loc,const TString & identifier,const TQualifier & qualifier,const TShaderQualifiers & publicType)4113 TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TString& identifier,
4114                                                  const TQualifier& qualifier, const TShaderQualifiers& publicType)
4115 {
4116 #ifndef GLSLANG_WEB
4117     if (! builtInName(identifier) || symbolTable.atBuiltInLevel() || ! symbolTable.atGlobalLevel())
4118         return nullptr;
4119 
4120     bool nonEsRedecls = (!isEsProfile() && (version >= 130 || identifier == "gl_TexCoord"));
4121     bool    esRedecls = (isEsProfile() &&
4122                          (version >= 320 || extensionsTurnedOn(Num_AEP_shader_io_blocks, AEP_shader_io_blocks)));
4123     if (! esRedecls && ! nonEsRedecls)
4124         return nullptr;
4125 
4126     // Special case when using GL_ARB_separate_shader_objects
4127     bool ssoPre150 = false;  // means the only reason this variable is redeclared is due to this combination
4128     if (!isEsProfile() && version <= 140 && extensionTurnedOn(E_GL_ARB_separate_shader_objects)) {
4129         if (identifier == "gl_Position"     ||
4130             identifier == "gl_PointSize"    ||
4131             identifier == "gl_ClipVertex"   ||
4132             identifier == "gl_FogFragCoord")
4133             ssoPre150 = true;
4134     }
4135 
4136     // Potentially redeclaring a built-in variable...
4137 
4138     if (ssoPre150 ||
4139         (identifier == "gl_FragDepth"           && ((nonEsRedecls && version >= 420) || esRedecls)) ||
4140         (identifier == "gl_FragCoord"           && ((nonEsRedecls && version >= 150) || esRedecls)) ||
4141          identifier == "gl_ClipDistance"                                                            ||
4142          identifier == "gl_CullDistance"                                                            ||
4143          identifier == "gl_FrontColor"                                                              ||
4144          identifier == "gl_BackColor"                                                               ||
4145          identifier == "gl_FrontSecondaryColor"                                                     ||
4146          identifier == "gl_BackSecondaryColor"                                                      ||
4147          identifier == "gl_SecondaryColor"                                                          ||
4148         (identifier == "gl_Color"               && language == EShLangFragment)                     ||
4149         (identifier == "gl_FragStencilRefARB"   && (nonEsRedecls && version >= 140)
4150                                                 && language == EShLangFragment)                     ||
4151          identifier == "gl_SampleMask"                                                              ||
4152          identifier == "gl_Layer"                                                                   ||
4153          identifier == "gl_PrimitiveIndicesNV"                                                      ||
4154          identifier == "gl_TexCoord") {
4155 
4156         // Find the existing symbol, if any.
4157         bool builtIn;
4158         TSymbol* symbol = symbolTable.find(identifier, &builtIn);
4159 
4160         // If the symbol was not found, this must be a version/profile/stage
4161         // that doesn't have it.
4162         if (! symbol)
4163             return nullptr;
4164 
4165         // If it wasn't at a built-in level, then it's already been redeclared;
4166         // that is, this is a redeclaration of a redeclaration; reuse that initial
4167         // redeclaration.  Otherwise, make the new one.
4168         if (builtIn)
4169             makeEditable(symbol);
4170 
4171         // Now, modify the type of the copy, as per the type of the current redeclaration.
4172 
4173         TQualifier& symbolQualifier = symbol->getWritableType().getQualifier();
4174         if (ssoPre150) {
4175             if (intermediate.inIoAccessed(identifier))
4176                 error(loc, "cannot redeclare after use", identifier.c_str(), "");
4177             if (qualifier.hasLayout())
4178                 error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str());
4179             if (qualifier.isMemory() || qualifier.isAuxiliary() || (language == EShLangVertex   && qualifier.storage != EvqVaryingOut) ||
4180                                                                    (language == EShLangFragment && qualifier.storage != EvqVaryingIn))
4181                 error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str());
4182             if (! qualifier.smooth)
4183                 error(loc, "cannot change interpolation qualification of", "redeclaration", symbol->getName().c_str());
4184         } else if (identifier == "gl_FrontColor"          ||
4185                    identifier == "gl_BackColor"           ||
4186                    identifier == "gl_FrontSecondaryColor" ||
4187                    identifier == "gl_BackSecondaryColor"  ||
4188                    identifier == "gl_SecondaryColor"      ||
4189                    identifier == "gl_Color") {
4190             symbolQualifier.flat = qualifier.flat;
4191             symbolQualifier.smooth = qualifier.smooth;
4192             symbolQualifier.nopersp = qualifier.nopersp;
4193             if (qualifier.hasLayout())
4194                 error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str());
4195             if (qualifier.isMemory() || qualifier.isAuxiliary() || symbol->getType().getQualifier().storage != qualifier.storage)
4196                 error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str());
4197         } else if (identifier == "gl_TexCoord"     ||
4198                    identifier == "gl_ClipDistance" ||
4199                    identifier == "gl_CullDistance") {
4200             if (qualifier.hasLayout() || qualifier.isMemory() || qualifier.isAuxiliary() ||
4201                 qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat ||
4202                 symbolQualifier.storage != qualifier.storage)
4203                 error(loc, "cannot change qualification of", "redeclaration", symbol->getName().c_str());
4204         } else if (identifier == "gl_FragCoord") {
4205             if (intermediate.inIoAccessed("gl_FragCoord"))
4206                 error(loc, "cannot redeclare after use", "gl_FragCoord", "");
4207             if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat ||
4208                 qualifier.isMemory() || qualifier.isAuxiliary())
4209                 error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str());
4210             if (qualifier.storage != EvqVaryingIn)
4211                 error(loc, "cannot change input storage qualification of", "redeclaration", symbol->getName().c_str());
4212             if (! builtIn && (publicType.pixelCenterInteger != intermediate.getPixelCenterInteger() ||
4213                               publicType.originUpperLeft != intermediate.getOriginUpperLeft()))
4214                 error(loc, "cannot redeclare with different qualification:", "redeclaration", symbol->getName().c_str());
4215             if (publicType.pixelCenterInteger)
4216                 intermediate.setPixelCenterInteger();
4217             if (publicType.originUpperLeft)
4218                 intermediate.setOriginUpperLeft();
4219         } else if (identifier == "gl_FragDepth") {
4220             if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat ||
4221                 qualifier.isMemory() || qualifier.isAuxiliary())
4222                 error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str());
4223             if (qualifier.storage != EvqVaryingOut)
4224                 error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str());
4225             if (publicType.layoutDepth != EldNone) {
4226                 if (intermediate.inIoAccessed("gl_FragDepth"))
4227                     error(loc, "cannot redeclare after use", "gl_FragDepth", "");
4228                 if (! intermediate.setDepth(publicType.layoutDepth))
4229                     error(loc, "all redeclarations must use the same depth layout on", "redeclaration", symbol->getName().c_str());
4230             }
4231         }
4232         else if (
4233             identifier == "gl_PrimitiveIndicesNV" ||
4234             identifier == "gl_FragStencilRefARB") {
4235             if (qualifier.hasLayout())
4236                 error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str());
4237             if (qualifier.storage != EvqVaryingOut)
4238                 error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str());
4239         }
4240         else if (identifier == "gl_SampleMask") {
4241             if (!publicType.layoutOverrideCoverage) {
4242                 error(loc, "redeclaration only allowed for override_coverage layout", "redeclaration", symbol->getName().c_str());
4243             }
4244             intermediate.setLayoutOverrideCoverage();
4245         }
4246         else if (identifier == "gl_Layer") {
4247             if (!qualifier.layoutViewportRelative && qualifier.layoutSecondaryViewportRelativeOffset == -2048)
4248                 error(loc, "redeclaration only allowed for viewport_relative or secondary_view_offset layout", "redeclaration", symbol->getName().c_str());
4249             symbolQualifier.layoutViewportRelative = qualifier.layoutViewportRelative;
4250             symbolQualifier.layoutSecondaryViewportRelativeOffset = qualifier.layoutSecondaryViewportRelativeOffset;
4251         }
4252 
4253         // TODO: semantics quality: separate smooth from nothing declared, then use IsInterpolation for several tests above
4254 
4255         return symbol;
4256     }
4257 #endif
4258 
4259     return nullptr;
4260 }
4261 
4262 //
4263 // Either redeclare the requested block, or give an error message why it can't be done.
4264 //
4265 // TODO: functionality: explicitly sizing members of redeclared blocks is not giving them an explicit size
redeclareBuiltinBlock(const TSourceLoc & loc,TTypeList & newTypeList,const TString & blockName,const TString * instanceName,TArraySizes * arraySizes)4266 void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newTypeList, const TString& blockName,
4267     const TString* instanceName, TArraySizes* arraySizes)
4268 {
4269 #ifndef GLSLANG_WEB
4270     const char* feature = "built-in block redeclaration";
4271     profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature);
4272     profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature);
4273 
4274     if (blockName != "gl_PerVertex" && blockName != "gl_PerFragment" &&
4275         blockName != "gl_MeshPerVertexNV" && blockName != "gl_MeshPerPrimitiveNV") {
4276         error(loc, "cannot redeclare block: ", "block declaration", blockName.c_str());
4277         return;
4278     }
4279 
4280     // Redeclaring a built-in block...
4281 
4282     if (instanceName && ! builtInName(*instanceName)) {
4283         error(loc, "cannot redeclare a built-in block with a user name", instanceName->c_str(), "");
4284         return;
4285     }
4286 
4287     // Blocks with instance names are easy to find, lookup the instance name,
4288     // Anonymous blocks need to be found via a member.
4289     bool builtIn;
4290     TSymbol* block;
4291     if (instanceName)
4292         block = symbolTable.find(*instanceName, &builtIn);
4293     else
4294         block = symbolTable.find(newTypeList.front().type->getFieldName(), &builtIn);
4295 
4296     // If the block was not found, this must be a version/profile/stage
4297     // that doesn't have it, or the instance name is wrong.
4298     const char* errorName = instanceName ? instanceName->c_str() : newTypeList.front().type->getFieldName().c_str();
4299     if (! block) {
4300         error(loc, "no declaration found for redeclaration", errorName, "");
4301         return;
4302     }
4303     // Built-in blocks cannot be redeclared more than once, which if happened,
4304     // we'd be finding the already redeclared one here, rather than the built in.
4305     if (! builtIn) {
4306         error(loc, "can only redeclare a built-in block once, and before any use", blockName.c_str(), "");
4307         return;
4308     }
4309 
4310     // Copy the block to make a writable version, to insert into the block table after editing.
4311     block = symbolTable.copyUpDeferredInsert(block);
4312 
4313     if (block->getType().getBasicType() != EbtBlock) {
4314         error(loc, "cannot redeclare a non block as a block", errorName, "");
4315         return;
4316     }
4317 
4318     // Fix XFB stuff up, it applies to the order of the redeclaration, not
4319     // the order of the original members.
4320     if (currentBlockQualifier.storage == EvqVaryingOut && globalOutputDefaults.hasXfbBuffer()) {
4321         if (!currentBlockQualifier.hasXfbBuffer())
4322             currentBlockQualifier.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer;
4323         if (!currentBlockQualifier.hasStream())
4324             currentBlockQualifier.layoutStream = globalOutputDefaults.layoutStream;
4325         fixXfbOffsets(currentBlockQualifier, newTypeList);
4326     }
4327 
4328     // Edit and error check the container against the redeclaration
4329     //  - remove unused members
4330     //  - ensure remaining qualifiers/types match
4331 
4332     TType& type = block->getWritableType();
4333 
4334     // if gl_PerVertex is redeclared for the purpose of passing through "gl_Position"
4335     // for passthrough purpose, the redeclared block should have the same qualifers as
4336     // the current one
4337     if (currentBlockQualifier.layoutPassthrough) {
4338         type.getQualifier().layoutPassthrough = currentBlockQualifier.layoutPassthrough;
4339         type.getQualifier().storage = currentBlockQualifier.storage;
4340         type.getQualifier().layoutStream = currentBlockQualifier.layoutStream;
4341         type.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer;
4342     }
4343 
4344     TTypeList::iterator member = type.getWritableStruct()->begin();
4345     size_t numOriginalMembersFound = 0;
4346     while (member != type.getStruct()->end()) {
4347         // look for match
4348         bool found = false;
4349         TTypeList::const_iterator newMember;
4350         TSourceLoc memberLoc;
4351         memberLoc.init();
4352         for (newMember = newTypeList.begin(); newMember != newTypeList.end(); ++newMember) {
4353             if (member->type->getFieldName() == newMember->type->getFieldName()) {
4354                 found = true;
4355                 memberLoc = newMember->loc;
4356                 break;
4357             }
4358         }
4359 
4360         if (found) {
4361             ++numOriginalMembersFound;
4362             // - ensure match between redeclared members' types
4363             // - check for things that can't be changed
4364             // - update things that can be changed
4365             TType& oldType = *member->type;
4366             const TType& newType = *newMember->type;
4367             if (! newType.sameElementType(oldType))
4368                 error(memberLoc, "cannot redeclare block member with a different type", member->type->getFieldName().c_str(), "");
4369             if (oldType.isArray() != newType.isArray())
4370                 error(memberLoc, "cannot change arrayness of redeclared block member", member->type->getFieldName().c_str(), "");
4371             else if (! oldType.getQualifier().isPerView() && ! oldType.sameArrayness(newType) && oldType.isSizedArray())
4372                 error(memberLoc, "cannot change array size of redeclared block member", member->type->getFieldName().c_str(), "");
4373             else if (! oldType.getQualifier().isPerView() && newType.isArray())
4374                 arrayLimitCheck(loc, member->type->getFieldName(), newType.getOuterArraySize());
4375             if (oldType.getQualifier().isPerView() && ! newType.getQualifier().isPerView())
4376                 error(memberLoc, "missing perviewNV qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
4377             else if (! oldType.getQualifier().isPerView() && newType.getQualifier().isPerView())
4378                 error(memberLoc, "cannot add perviewNV qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
4379             else if (newType.getQualifier().isPerView()) {
4380                 if (oldType.getArraySizes()->getNumDims() != newType.getArraySizes()->getNumDims())
4381                     error(memberLoc, "cannot change arrayness of redeclared block member", member->type->getFieldName().c_str(), "");
4382                 else if (! newType.isUnsizedArray() && newType.getOuterArraySize() != resources.maxMeshViewCountNV)
4383                     error(loc, "mesh view output array size must be gl_MaxMeshViewCountNV or implicitly sized", "[]", "");
4384                 else if (newType.getArraySizes()->getNumDims() == 2) {
4385                     int innerDimSize = newType.getArraySizes()->getDimSize(1);
4386                     arrayLimitCheck(memberLoc, member->type->getFieldName(), innerDimSize);
4387                     oldType.getArraySizes()->setDimSize(1, innerDimSize);
4388                 }
4389             }
4390             if (oldType.getQualifier().isPerPrimitive() && ! newType.getQualifier().isPerPrimitive())
4391                 error(memberLoc, "missing perprimitiveNV qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
4392             else if (! oldType.getQualifier().isPerPrimitive() && newType.getQualifier().isPerPrimitive())
4393                 error(memberLoc, "cannot add perprimitiveNV qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
4394             if (newType.getQualifier().isMemory())
4395                 error(memberLoc, "cannot add memory qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
4396             if (newType.getQualifier().hasNonXfbLayout())
4397                 error(memberLoc, "cannot add non-XFB layout to redeclared block member", member->type->getFieldName().c_str(), "");
4398             if (newType.getQualifier().patch)
4399                 error(memberLoc, "cannot add patch to redeclared block member", member->type->getFieldName().c_str(), "");
4400             if (newType.getQualifier().hasXfbBuffer() &&
4401                 newType.getQualifier().layoutXfbBuffer != currentBlockQualifier.layoutXfbBuffer)
4402                 error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", "");
4403             if (newType.getQualifier().hasStream() &&
4404                 newType.getQualifier().layoutStream != currentBlockQualifier.layoutStream)
4405                 error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_stream", "");
4406             oldType.getQualifier().centroid = newType.getQualifier().centroid;
4407             oldType.getQualifier().sample = newType.getQualifier().sample;
4408             oldType.getQualifier().invariant = newType.getQualifier().invariant;
4409             oldType.getQualifier().noContraction = newType.getQualifier().noContraction;
4410             oldType.getQualifier().smooth = newType.getQualifier().smooth;
4411             oldType.getQualifier().flat = newType.getQualifier().flat;
4412             oldType.getQualifier().nopersp = newType.getQualifier().nopersp;
4413             oldType.getQualifier().layoutXfbOffset = newType.getQualifier().layoutXfbOffset;
4414             oldType.getQualifier().layoutXfbBuffer = newType.getQualifier().layoutXfbBuffer;
4415             oldType.getQualifier().layoutXfbStride = newType.getQualifier().layoutXfbStride;
4416             if (oldType.getQualifier().layoutXfbOffset != TQualifier::layoutXfbBufferEnd) {
4417                 // If any member has an xfb_offset, then the block's xfb_buffer inherents current xfb_buffer,
4418                 // and for xfb processing, the member needs it as well, along with xfb_stride.
4419                 type.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer;
4420                 oldType.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer;
4421             }
4422             if (oldType.isUnsizedArray() && newType.isSizedArray())
4423                 oldType.changeOuterArraySize(newType.getOuterArraySize());
4424 
4425             //  check and process the member's type, which will include managing xfb information
4426             layoutTypeCheck(loc, oldType);
4427 
4428             // go to next member
4429             ++member;
4430         } else {
4431             // For missing members of anonymous blocks that have been redeclared,
4432             // hide the original (shared) declaration.
4433             // Instance-named blocks can just have the member removed.
4434             if (instanceName)
4435                 member = type.getWritableStruct()->erase(member);
4436             else {
4437                 member->type->hideMember();
4438                 ++member;
4439             }
4440         }
4441     }
4442 
4443     if (spvVersion.vulkan > 0) {
4444         // ...then streams apply to built-in blocks, instead of them being only on stream 0
4445         type.getQualifier().layoutStream = currentBlockQualifier.layoutStream;
4446     }
4447 
4448     if (numOriginalMembersFound < newTypeList.size())
4449         error(loc, "block redeclaration has extra members", blockName.c_str(), "");
4450     if (type.isArray() != (arraySizes != nullptr) ||
4451         (type.isArray() && arraySizes != nullptr && type.getArraySizes()->getNumDims() != arraySizes->getNumDims()))
4452         error(loc, "cannot change arrayness of redeclared block", blockName.c_str(), "");
4453     else if (type.isArray()) {
4454         // At this point, we know both are arrays and both have the same number of dimensions.
4455 
4456         // It is okay for a built-in block redeclaration to be unsized, and keep the size of the
4457         // original block declaration.
4458         if (!arraySizes->isSized() && type.isSizedArray())
4459             arraySizes->changeOuterSize(type.getOuterArraySize());
4460 
4461         // And, okay to be giving a size to the array, by the redeclaration
4462         if (!type.isSizedArray() && arraySizes->isSized())
4463             type.changeOuterArraySize(arraySizes->getOuterSize());
4464 
4465         // Now, they must match in all dimensions.
4466         if (type.isSizedArray() && *type.getArraySizes() != *arraySizes)
4467             error(loc, "cannot change array size of redeclared block", blockName.c_str(), "");
4468     }
4469 
4470     symbolTable.insert(*block);
4471 
4472     // Check for general layout qualifier errors
4473     layoutObjectCheck(loc, *block);
4474 
4475     // Tracking for implicit sizing of array
4476     if (isIoResizeArray(block->getType())) {
4477         ioArraySymbolResizeList.push_back(block);
4478         checkIoArraysConsistency(loc, true);
4479     } else if (block->getType().isArray())
4480         fixIoArraySize(loc, block->getWritableType());
4481 
4482     // Save it in the AST for linker use.
4483     trackLinkage(*block);
4484 #endif // GLSLANG_WEB
4485 }
4486 
paramCheckFixStorage(const TSourceLoc & loc,const TStorageQualifier & qualifier,TType & type)4487 void TParseContext::paramCheckFixStorage(const TSourceLoc& loc, const TStorageQualifier& qualifier, TType& type)
4488 {
4489     switch (qualifier) {
4490     case EvqConst:
4491     case EvqConstReadOnly:
4492         type.getQualifier().storage = EvqConstReadOnly;
4493         break;
4494     case EvqIn:
4495     case EvqOut:
4496     case EvqInOut:
4497         type.getQualifier().storage = qualifier;
4498         break;
4499     case EvqGlobal:
4500     case EvqTemporary:
4501         type.getQualifier().storage = EvqIn;
4502         break;
4503     default:
4504         type.getQualifier().storage = EvqIn;
4505         error(loc, "storage qualifier not allowed on function parameter", GetStorageQualifierString(qualifier), "");
4506         break;
4507     }
4508 }
4509 
paramCheckFix(const TSourceLoc & loc,const TQualifier & qualifier,TType & type)4510 void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& qualifier, TType& type)
4511 {
4512 #ifndef GLSLANG_WEB
4513     if (qualifier.isMemory()) {
4514         type.getQualifier().volatil   = qualifier.volatil;
4515         type.getQualifier().coherent  = qualifier.coherent;
4516         type.getQualifier().devicecoherent  = qualifier.devicecoherent ;
4517         type.getQualifier().queuefamilycoherent  = qualifier.queuefamilycoherent;
4518         type.getQualifier().workgroupcoherent  = qualifier.workgroupcoherent;
4519         type.getQualifier().subgroupcoherent  = qualifier.subgroupcoherent;
4520         type.getQualifier().shadercallcoherent = qualifier.shadercallcoherent;
4521         type.getQualifier().nonprivate = qualifier.nonprivate;
4522         type.getQualifier().readonly  = qualifier.readonly;
4523         type.getQualifier().writeonly = qualifier.writeonly;
4524         type.getQualifier().restrict  = qualifier.restrict;
4525     }
4526 #endif
4527 
4528     if (qualifier.isAuxiliary() ||
4529         qualifier.isInterpolation())
4530         error(loc, "cannot use auxiliary or interpolation qualifiers on a function parameter", "", "");
4531     if (qualifier.hasLayout())
4532         error(loc, "cannot use layout qualifiers on a function parameter", "", "");
4533     if (qualifier.invariant)
4534         error(loc, "cannot use invariant qualifier on a function parameter", "", "");
4535     if (qualifier.isNoContraction()) {
4536         if (qualifier.isParamOutput())
4537             type.getQualifier().setNoContraction();
4538         else
4539             warn(loc, "qualifier has no effect on non-output parameters", "precise", "");
4540     }
4541     if (qualifier.isNonUniform())
4542         type.getQualifier().nonUniform = qualifier.nonUniform;
4543 
4544     paramCheckFixStorage(loc, qualifier.storage, type);
4545 }
4546 
nestedBlockCheck(const TSourceLoc & loc)4547 void TParseContext::nestedBlockCheck(const TSourceLoc& loc)
4548 {
4549     if (structNestingLevel > 0)
4550         error(loc, "cannot nest a block definition inside a structure or block", "", "");
4551     ++structNestingLevel;
4552 }
4553 
nestedStructCheck(const TSourceLoc & loc)4554 void TParseContext::nestedStructCheck(const TSourceLoc& loc)
4555 {
4556     if (structNestingLevel > 0)
4557         error(loc, "cannot nest a structure definition inside a structure or block", "", "");
4558     ++structNestingLevel;
4559 }
4560 
arrayObjectCheck(const TSourceLoc & loc,const TType & type,const char * op)4561 void TParseContext::arrayObjectCheck(const TSourceLoc& loc, const TType& type, const char* op)
4562 {
4563     // Some versions don't allow comparing arrays or structures containing arrays
4564     if (type.containsArray()) {
4565         profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, op);
4566         profileRequires(loc, EEsProfile, 300, nullptr, op);
4567     }
4568 }
4569 
opaqueCheck(const TSourceLoc & loc,const TType & type,const char * op)4570 void TParseContext::opaqueCheck(const TSourceLoc& loc, const TType& type, const char* op)
4571 {
4572     if (containsFieldWithBasicType(type, EbtSampler))
4573         error(loc, "can't use with samplers or structs containing samplers", op, "");
4574 }
4575 
referenceCheck(const TSourceLoc & loc,const TType & type,const char * op)4576 void TParseContext::referenceCheck(const TSourceLoc& loc, const TType& type, const char* op)
4577 {
4578 #ifndef GLSLANG_WEB
4579     if (containsFieldWithBasicType(type, EbtReference))
4580         error(loc, "can't use with reference types", op, "");
4581 #endif
4582 }
4583 
storage16BitAssignmentCheck(const TSourceLoc & loc,const TType & type,const char * op)4584 void TParseContext::storage16BitAssignmentCheck(const TSourceLoc& loc, const TType& type, const char* op)
4585 {
4586 #ifndef GLSLANG_WEB
4587     if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtFloat16))
4588         requireFloat16Arithmetic(loc, op, "can't use with structs containing float16");
4589 
4590     if (type.isArray() && type.getBasicType() == EbtFloat16)
4591         requireFloat16Arithmetic(loc, op, "can't use with arrays containing float16");
4592 
4593     if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtInt16))
4594         requireInt16Arithmetic(loc, op, "can't use with structs containing int16");
4595 
4596     if (type.isArray() && type.getBasicType() == EbtInt16)
4597         requireInt16Arithmetic(loc, op, "can't use with arrays containing int16");
4598 
4599     if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtUint16))
4600         requireInt16Arithmetic(loc, op, "can't use with structs containing uint16");
4601 
4602     if (type.isArray() && type.getBasicType() == EbtUint16)
4603         requireInt16Arithmetic(loc, op, "can't use with arrays containing uint16");
4604 
4605     if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtInt8))
4606         requireInt8Arithmetic(loc, op, "can't use with structs containing int8");
4607 
4608     if (type.isArray() && type.getBasicType() == EbtInt8)
4609         requireInt8Arithmetic(loc, op, "can't use with arrays containing int8");
4610 
4611     if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtUint8))
4612         requireInt8Arithmetic(loc, op, "can't use with structs containing uint8");
4613 
4614     if (type.isArray() && type.getBasicType() == EbtUint8)
4615         requireInt8Arithmetic(loc, op, "can't use with arrays containing uint8");
4616 #endif
4617 }
4618 
specializationCheck(const TSourceLoc & loc,const TType & type,const char * op)4619 void TParseContext::specializationCheck(const TSourceLoc& loc, const TType& type, const char* op)
4620 {
4621     if (type.containsSpecializationSize())
4622         error(loc, "can't use with types containing arrays sized with a specialization constant", op, "");
4623 }
4624 
structTypeCheck(const TSourceLoc &,TPublicType & publicType)4625 void TParseContext::structTypeCheck(const TSourceLoc& /*loc*/, TPublicType& publicType)
4626 {
4627     const TTypeList& typeList = *publicType.userDef->getStruct();
4628 
4629     // fix and check for member storage qualifiers and types that don't belong within a structure
4630     for (unsigned int member = 0; member < typeList.size(); ++member) {
4631         TQualifier& memberQualifier = typeList[member].type->getQualifier();
4632         const TSourceLoc& memberLoc = typeList[member].loc;
4633         if (memberQualifier.isAuxiliary() ||
4634             memberQualifier.isInterpolation() ||
4635             (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal))
4636             error(memberLoc, "cannot use storage or interpolation qualifiers on structure members", typeList[member].type->getFieldName().c_str(), "");
4637         if (memberQualifier.isMemory())
4638             error(memberLoc, "cannot use memory qualifiers on structure members", typeList[member].type->getFieldName().c_str(), "");
4639         if (memberQualifier.hasLayout()) {
4640             error(memberLoc, "cannot use layout qualifiers on structure members", typeList[member].type->getFieldName().c_str(), "");
4641             memberQualifier.clearLayout();
4642         }
4643         if (memberQualifier.invariant)
4644             error(memberLoc, "cannot use invariant qualifier on structure members", typeList[member].type->getFieldName().c_str(), "");
4645     }
4646 }
4647 
4648 //
4649 // See if this loop satisfies the limitations for ES 2.0 (version 100) for loops in Appendex A:
4650 //
4651 // "The loop index has type int or float.
4652 //
4653 // "The for statement has the form:
4654 //     for ( init-declaration ; condition ; expression )
4655 //     init-declaration has the form: type-specifier identifier = constant-expression
4656 //     condition has the form:  loop-index relational_operator constant-expression
4657 //         where relational_operator is one of: > >= < <= == or !=
4658 //     expression [sic] has one of the following forms:
4659 //         loop-index++
4660 //         loop-index--
4661 //         loop-index += constant-expression
4662 //         loop-index -= constant-expression
4663 //
4664 // The body is handled in an AST traversal.
4665 //
inductiveLoopCheck(const TSourceLoc & loc,TIntermNode * init,TIntermLoop * loop)4666 void TParseContext::inductiveLoopCheck(const TSourceLoc& loc, TIntermNode* init, TIntermLoop* loop)
4667 {
4668 #ifndef GLSLANG_WEB
4669     // loop index init must exist and be a declaration, which shows up in the AST as an aggregate of size 1 of the declaration
4670     bool badInit = false;
4671     if (! init || ! init->getAsAggregate() || init->getAsAggregate()->getSequence().size() != 1)
4672         badInit = true;
4673     TIntermBinary* binaryInit = 0;
4674     if (! badInit) {
4675         // get the declaration assignment
4676         binaryInit = init->getAsAggregate()->getSequence()[0]->getAsBinaryNode();
4677         if (! binaryInit)
4678             badInit = true;
4679     }
4680     if (badInit) {
4681         error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", "");
4682         return;
4683     }
4684 
4685     // loop index must be type int or float
4686     if (! binaryInit->getType().isScalar() || (binaryInit->getBasicType() != EbtInt && binaryInit->getBasicType() != EbtFloat)) {
4687         error(loc, "inductive loop requires a scalar 'int' or 'float' loop index", "limitations", "");
4688         return;
4689     }
4690 
4691     // init is the form "loop-index = constant"
4692     if (binaryInit->getOp() != EOpAssign || ! binaryInit->getLeft()->getAsSymbolNode() || ! binaryInit->getRight()->getAsConstantUnion()) {
4693         error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", "");
4694         return;
4695     }
4696 
4697     // get the unique id of the loop index
4698     int loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId();
4699     inductiveLoopIds.insert(loopIndex);
4700 
4701     // condition's form must be "loop-index relational-operator constant-expression"
4702     bool badCond = ! loop->getTest();
4703     if (! badCond) {
4704         TIntermBinary* binaryCond = loop->getTest()->getAsBinaryNode();
4705         badCond = ! binaryCond;
4706         if (! badCond) {
4707             switch (binaryCond->getOp()) {
4708             case EOpGreaterThan:
4709             case EOpGreaterThanEqual:
4710             case EOpLessThan:
4711             case EOpLessThanEqual:
4712             case EOpEqual:
4713             case EOpNotEqual:
4714                 break;
4715             default:
4716                 badCond = true;
4717             }
4718         }
4719         if (binaryCond && (! binaryCond->getLeft()->getAsSymbolNode() ||
4720                            binaryCond->getLeft()->getAsSymbolNode()->getId() != loopIndex ||
4721                            ! binaryCond->getRight()->getAsConstantUnion()))
4722             badCond = true;
4723     }
4724     if (badCond) {
4725         error(loc, "inductive-loop condition requires the form \"loop-index <comparison-op> constant-expression\"", "limitations", "");
4726         return;
4727     }
4728 
4729     // loop-index++
4730     // loop-index--
4731     // loop-index += constant-expression
4732     // loop-index -= constant-expression
4733     bool badTerminal = ! loop->getTerminal();
4734     if (! badTerminal) {
4735         TIntermUnary* unaryTerminal = loop->getTerminal()->getAsUnaryNode();
4736         TIntermBinary* binaryTerminal = loop->getTerminal()->getAsBinaryNode();
4737         if (unaryTerminal || binaryTerminal) {
4738             switch(loop->getTerminal()->getAsOperator()->getOp()) {
4739             case EOpPostDecrement:
4740             case EOpPostIncrement:
4741             case EOpAddAssign:
4742             case EOpSubAssign:
4743                 break;
4744             default:
4745                 badTerminal = true;
4746             }
4747         } else
4748             badTerminal = true;
4749         if (binaryTerminal && (! binaryTerminal->getLeft()->getAsSymbolNode() ||
4750                                binaryTerminal->getLeft()->getAsSymbolNode()->getId() != loopIndex ||
4751                                ! binaryTerminal->getRight()->getAsConstantUnion()))
4752             badTerminal = true;
4753         if (unaryTerminal && (! unaryTerminal->getOperand()->getAsSymbolNode() ||
4754                               unaryTerminal->getOperand()->getAsSymbolNode()->getId() != loopIndex))
4755             badTerminal = true;
4756     }
4757     if (badTerminal) {
4758         error(loc, "inductive-loop termination requires the form \"loop-index++, loop-index--, loop-index += constant-expression, or loop-index -= constant-expression\"", "limitations", "");
4759         return;
4760     }
4761 
4762     // the body
4763     inductiveLoopBodyCheck(loop->getBody(), loopIndex, symbolTable);
4764 #endif
4765 }
4766 
4767 #ifndef GLSLANG_WEB
4768 // Do limit checks for built-in arrays.
arrayLimitCheck(const TSourceLoc & loc,const TString & identifier,int size)4769 void TParseContext::arrayLimitCheck(const TSourceLoc& loc, const TString& identifier, int size)
4770 {
4771     if (identifier.compare("gl_TexCoord") == 0)
4772         limitCheck(loc, size, "gl_MaxTextureCoords", "gl_TexCoord array size");
4773     else if (identifier.compare("gl_ClipDistance") == 0)
4774         limitCheck(loc, size, "gl_MaxClipDistances", "gl_ClipDistance array size");
4775     else if (identifier.compare("gl_CullDistance") == 0)
4776         limitCheck(loc, size, "gl_MaxCullDistances", "gl_CullDistance array size");
4777     else if (identifier.compare("gl_ClipDistancePerViewNV") == 0)
4778         limitCheck(loc, size, "gl_MaxClipDistances", "gl_ClipDistancePerViewNV array size");
4779     else if (identifier.compare("gl_CullDistancePerViewNV") == 0)
4780         limitCheck(loc, size, "gl_MaxCullDistances", "gl_CullDistancePerViewNV array size");
4781 }
4782 #endif // GLSLANG_WEB
4783 
4784 // See if the provided value is less than or equal to the symbol indicated by limit,
4785 // which should be a constant in the symbol table.
limitCheck(const TSourceLoc & loc,int value,const char * limit,const char * feature)4786 void TParseContext::limitCheck(const TSourceLoc& loc, int value, const char* limit, const char* feature)
4787 {
4788     TSymbol* symbol = symbolTable.find(limit);
4789     assert(symbol->getAsVariable());
4790     const TConstUnionArray& constArray = symbol->getAsVariable()->getConstArray();
4791     assert(! constArray.empty());
4792     if (value > constArray[0].getIConst())
4793         error(loc, "must be less than or equal to", feature, "%s (%d)", limit, constArray[0].getIConst());
4794 }
4795 
4796 #ifndef GLSLANG_WEB
4797 
4798 //
4799 // Do any additional error checking, etc., once we know the parsing is done.
4800 //
finish()4801 void TParseContext::finish()
4802 {
4803     TParseContextBase::finish();
4804 
4805     if (parsingBuiltins)
4806         return;
4807 
4808     // Check on array indexes for ES 2.0 (version 100) limitations.
4809     for (size_t i = 0; i < needsIndexLimitationChecking.size(); ++i)
4810         constantIndexExpressionCheck(needsIndexLimitationChecking[i]);
4811 
4812     // Check for stages that are enabled by extension.
4813     // Can't do this at the beginning, it is chicken and egg to add a stage by
4814     // extension.
4815     // Stage-specific features were correctly tested for already, this is just
4816     // about the stage itself.
4817     switch (language) {
4818     case EShLangGeometry:
4819         if (isEsProfile() && version == 310)
4820             requireExtensions(getCurrentLoc(), Num_AEP_geometry_shader, AEP_geometry_shader, "geometry shaders");
4821         break;
4822     case EShLangTessControl:
4823     case EShLangTessEvaluation:
4824         if (isEsProfile() && version == 310)
4825             requireExtensions(getCurrentLoc(), Num_AEP_tessellation_shader, AEP_tessellation_shader, "tessellation shaders");
4826         else if (!isEsProfile() && version < 400)
4827             requireExtensions(getCurrentLoc(), 1, &E_GL_ARB_tessellation_shader, "tessellation shaders");
4828         break;
4829     case EShLangCompute:
4830         if (!isEsProfile() && version < 430)
4831             requireExtensions(getCurrentLoc(), 1, &E_GL_ARB_compute_shader, "compute shaders");
4832         break;
4833     case EShLangTaskNV:
4834         requireExtensions(getCurrentLoc(), 1, &E_GL_NV_mesh_shader, "task shaders");
4835         break;
4836     case EShLangMeshNV:
4837         requireExtensions(getCurrentLoc(), 1, &E_GL_NV_mesh_shader, "mesh shaders");
4838         break;
4839     default:
4840         break;
4841     }
4842 
4843     // Set default outputs for GL_NV_geometry_shader_passthrough
4844     if (language == EShLangGeometry && extensionTurnedOn(E_SPV_NV_geometry_shader_passthrough)) {
4845         if (intermediate.getOutputPrimitive() == ElgNone) {
4846             switch (intermediate.getInputPrimitive()) {
4847             case ElgPoints:      intermediate.setOutputPrimitive(ElgPoints);    break;
4848             case ElgLines:       intermediate.setOutputPrimitive(ElgLineStrip); break;
4849             case ElgTriangles:   intermediate.setOutputPrimitive(ElgTriangleStrip); break;
4850             default: break;
4851             }
4852         }
4853         if (intermediate.getVertices() == TQualifier::layoutNotSet) {
4854             switch (intermediate.getInputPrimitive()) {
4855             case ElgPoints:      intermediate.setVertices(1); break;
4856             case ElgLines:       intermediate.setVertices(2); break;
4857             case ElgTriangles:   intermediate.setVertices(3); break;
4858             default: break;
4859             }
4860         }
4861     }
4862 }
4863 #endif // GLSLANG_WEB
4864 
4865 //
4866 // Layout qualifier stuff.
4867 //
4868 
4869 // Put the id's layout qualification into the public type, for qualifiers not having a number set.
4870 // This is before we know any type information for error checking.
setLayoutQualifier(const TSourceLoc & loc,TPublicType & publicType,TString & id)4871 void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publicType, TString& id)
4872 {
4873     std::transform(id.begin(), id.end(), id.begin(), ::tolower);
4874 
4875     if (id == TQualifier::getLayoutMatrixString(ElmColumnMajor)) {
4876         publicType.qualifier.layoutMatrix = ElmColumnMajor;
4877         return;
4878     }
4879     if (id == TQualifier::getLayoutMatrixString(ElmRowMajor)) {
4880         publicType.qualifier.layoutMatrix = ElmRowMajor;
4881         return;
4882     }
4883     if (id == TQualifier::getLayoutPackingString(ElpPacked)) {
4884         if (spvVersion.spv != 0)
4885             spvRemoved(loc, "packed");
4886         publicType.qualifier.layoutPacking = ElpPacked;
4887         return;
4888     }
4889     if (id == TQualifier::getLayoutPackingString(ElpShared)) {
4890         if (spvVersion.spv != 0)
4891             spvRemoved(loc, "shared");
4892         publicType.qualifier.layoutPacking = ElpShared;
4893         return;
4894     }
4895     if (id == TQualifier::getLayoutPackingString(ElpStd140)) {
4896         publicType.qualifier.layoutPacking = ElpStd140;
4897         return;
4898     }
4899 #ifndef GLSLANG_WEB
4900     if (id == TQualifier::getLayoutPackingString(ElpStd430)) {
4901         requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "std430");
4902         profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "std430");
4903         profileRequires(loc, EEsProfile, 310, nullptr, "std430");
4904         publicType.qualifier.layoutPacking = ElpStd430;
4905         return;
4906     }
4907     if (id == TQualifier::getLayoutPackingString(ElpScalar)) {
4908         requireVulkan(loc, "scalar");
4909         requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "scalar block layout");
4910         publicType.qualifier.layoutPacking = ElpScalar;
4911         return;
4912     }
4913     // TODO: compile-time performance: may need to stop doing linear searches
4914     for (TLayoutFormat format = (TLayoutFormat)(ElfNone + 1); format < ElfCount; format = (TLayoutFormat)(format + 1)) {
4915         if (id == TQualifier::getLayoutFormatString(format)) {
4916             if ((format > ElfEsFloatGuard && format < ElfFloatGuard) ||
4917                 (format > ElfEsIntGuard && format < ElfIntGuard) ||
4918                 (format > ElfEsUintGuard && format < ElfCount))
4919                 requireProfile(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, "image load-store format");
4920             profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_ARB_shader_image_load_store, "image load store");
4921             profileRequires(loc, EEsProfile, 310, E_GL_ARB_shader_image_load_store, "image load store");
4922             publicType.qualifier.layoutFormat = format;
4923             return;
4924         }
4925     }
4926     if (id == "push_constant") {
4927         requireVulkan(loc, "push_constant");
4928         publicType.qualifier.layoutPushConstant = true;
4929         return;
4930     }
4931     if (id == "buffer_reference") {
4932         requireVulkan(loc, "buffer_reference");
4933         requireExtensions(loc, 1, &E_GL_EXT_buffer_reference, "buffer_reference");
4934         publicType.qualifier.layoutBufferReference = true;
4935         intermediate.setUseStorageBuffer();
4936         intermediate.setUsePhysicalStorageBuffer();
4937         return;
4938     }
4939     if (language == EShLangGeometry || language == EShLangTessEvaluation || language == EShLangMeshNV) {
4940         if (id == TQualifier::getGeometryString(ElgTriangles)) {
4941             publicType.shaderQualifiers.geometry = ElgTriangles;
4942             return;
4943         }
4944         if (language == EShLangGeometry || language == EShLangMeshNV) {
4945             if (id == TQualifier::getGeometryString(ElgPoints)) {
4946                 publicType.shaderQualifiers.geometry = ElgPoints;
4947                 return;
4948             }
4949             if (id == TQualifier::getGeometryString(ElgLines)) {
4950                 publicType.shaderQualifiers.geometry = ElgLines;
4951                 return;
4952             }
4953             if (language == EShLangGeometry) {
4954                 if (id == TQualifier::getGeometryString(ElgLineStrip)) {
4955                     publicType.shaderQualifiers.geometry = ElgLineStrip;
4956                     return;
4957                 }
4958                 if (id == TQualifier::getGeometryString(ElgLinesAdjacency)) {
4959                     publicType.shaderQualifiers.geometry = ElgLinesAdjacency;
4960                     return;
4961                 }
4962                 if (id == TQualifier::getGeometryString(ElgTrianglesAdjacency)) {
4963                     publicType.shaderQualifiers.geometry = ElgTrianglesAdjacency;
4964                     return;
4965                 }
4966                 if (id == TQualifier::getGeometryString(ElgTriangleStrip)) {
4967                     publicType.shaderQualifiers.geometry = ElgTriangleStrip;
4968                     return;
4969                 }
4970                 if (id == "passthrough") {
4971                     requireExtensions(loc, 1, &E_SPV_NV_geometry_shader_passthrough, "geometry shader passthrough");
4972                     publicType.qualifier.layoutPassthrough = true;
4973                     intermediate.setGeoPassthroughEXT();
4974                     return;
4975                 }
4976             }
4977         } else {
4978             assert(language == EShLangTessEvaluation);
4979 
4980             // input primitive
4981             if (id == TQualifier::getGeometryString(ElgTriangles)) {
4982                 publicType.shaderQualifiers.geometry = ElgTriangles;
4983                 return;
4984             }
4985             if (id == TQualifier::getGeometryString(ElgQuads)) {
4986                 publicType.shaderQualifiers.geometry = ElgQuads;
4987                 return;
4988             }
4989             if (id == TQualifier::getGeometryString(ElgIsolines)) {
4990                 publicType.shaderQualifiers.geometry = ElgIsolines;
4991                 return;
4992             }
4993 
4994             // vertex spacing
4995             if (id == TQualifier::getVertexSpacingString(EvsEqual)) {
4996                 publicType.shaderQualifiers.spacing = EvsEqual;
4997                 return;
4998             }
4999             if (id == TQualifier::getVertexSpacingString(EvsFractionalEven)) {
5000                 publicType.shaderQualifiers.spacing = EvsFractionalEven;
5001                 return;
5002             }
5003             if (id == TQualifier::getVertexSpacingString(EvsFractionalOdd)) {
5004                 publicType.shaderQualifiers.spacing = EvsFractionalOdd;
5005                 return;
5006             }
5007 
5008             // triangle order
5009             if (id == TQualifier::getVertexOrderString(EvoCw)) {
5010                 publicType.shaderQualifiers.order = EvoCw;
5011                 return;
5012             }
5013             if (id == TQualifier::getVertexOrderString(EvoCcw)) {
5014                 publicType.shaderQualifiers.order = EvoCcw;
5015                 return;
5016             }
5017 
5018             // point mode
5019             if (id == "point_mode") {
5020                 publicType.shaderQualifiers.pointMode = true;
5021                 return;
5022             }
5023         }
5024     }
5025     if (language == EShLangFragment) {
5026         if (id == "origin_upper_left") {
5027             requireProfile(loc, ECoreProfile | ECompatibilityProfile, "origin_upper_left");
5028             publicType.shaderQualifiers.originUpperLeft = true;
5029             return;
5030         }
5031         if (id == "pixel_center_integer") {
5032             requireProfile(loc, ECoreProfile | ECompatibilityProfile, "pixel_center_integer");
5033             publicType.shaderQualifiers.pixelCenterInteger = true;
5034             return;
5035         }
5036         if (id == "early_fragment_tests") {
5037             profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_ARB_shader_image_load_store, "early_fragment_tests");
5038             profileRequires(loc, EEsProfile, 310, nullptr, "early_fragment_tests");
5039             publicType.shaderQualifiers.earlyFragmentTests = true;
5040             return;
5041         }
5042         if (id == "post_depth_coverage") {
5043             requireExtensions(loc, Num_post_depth_coverageEXTs, post_depth_coverageEXTs, "post depth coverage");
5044             if (extensionTurnedOn(E_GL_ARB_post_depth_coverage)) {
5045                 publicType.shaderQualifiers.earlyFragmentTests = true;
5046             }
5047             publicType.shaderQualifiers.postDepthCoverage = true;
5048             return;
5049         }
5050         for (TLayoutDepth depth = (TLayoutDepth)(EldNone + 1); depth < EldCount; depth = (TLayoutDepth)(depth+1)) {
5051             if (id == TQualifier::getLayoutDepthString(depth)) {
5052                 requireProfile(loc, ECoreProfile | ECompatibilityProfile, "depth layout qualifier");
5053                 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, nullptr, "depth layout qualifier");
5054                 publicType.shaderQualifiers.layoutDepth = depth;
5055                 return;
5056             }
5057         }
5058         for (TInterlockOrdering order = (TInterlockOrdering)(EioNone + 1); order < EioCount; order = (TInterlockOrdering)(order+1)) {
5059             if (id == TQualifier::getInterlockOrderingString(order)) {
5060                 requireProfile(loc, ECoreProfile | ECompatibilityProfile, "fragment shader interlock layout qualifier");
5061                 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 450, nullptr, "fragment shader interlock layout qualifier");
5062                 requireExtensions(loc, 1, &E_GL_ARB_fragment_shader_interlock, TQualifier::getInterlockOrderingString(order));
5063                 if (order == EioShadingRateInterlockOrdered || order == EioShadingRateInterlockUnordered)
5064                     requireExtensions(loc, 1, &E_GL_NV_shading_rate_image, TQualifier::getInterlockOrderingString(order));
5065                 publicType.shaderQualifiers.interlockOrdering = order;
5066                 return;
5067             }
5068         }
5069         if (id.compare(0, 13, "blend_support") == 0) {
5070             bool found = false;
5071             for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) {
5072                 if (id == TQualifier::getBlendEquationString(be)) {
5073                     profileRequires(loc, EEsProfile, 320, E_GL_KHR_blend_equation_advanced, "blend equation");
5074                     profileRequires(loc, ~EEsProfile, 0, E_GL_KHR_blend_equation_advanced, "blend equation");
5075                     intermediate.addBlendEquation(be);
5076                     publicType.shaderQualifiers.blendEquation = true;
5077                     found = true;
5078                     break;
5079                 }
5080             }
5081             if (! found)
5082                 error(loc, "unknown blend equation", "blend_support", "");
5083             return;
5084         }
5085         if (id == "override_coverage") {
5086             requireExtensions(loc, 1, &E_GL_NV_sample_mask_override_coverage, "sample mask override coverage");
5087             publicType.shaderQualifiers.layoutOverrideCoverage = true;
5088             return;
5089         }
5090     }
5091     if (language == EShLangVertex ||
5092         language == EShLangTessControl ||
5093         language == EShLangTessEvaluation ||
5094         language == EShLangGeometry ) {
5095         if (id == "viewport_relative") {
5096             requireExtensions(loc, 1, &E_GL_NV_viewport_array2, "view port array2");
5097             publicType.qualifier.layoutViewportRelative = true;
5098             return;
5099         }
5100     } else {
5101         if (language == EShLangRayGen || language == EShLangIntersect ||
5102         language == EShLangAnyHit || language == EShLangClosestHit ||
5103         language == EShLangMiss || language == EShLangCallable) {
5104             if (id == "shaderrecordnv" || id == "shaderrecordext") {
5105                 if (id == "shaderrecordnv") {
5106                     requireExtensions(loc, 1, &E_GL_NV_ray_tracing, "shader record NV");
5107                 } else {
5108                     requireExtensions(loc, 1, &E_GL_EXT_ray_tracing, "shader record EXT");
5109                 }
5110                 publicType.qualifier.layoutShaderRecord = true;
5111                 return;
5112             }
5113 
5114         }
5115     }
5116     if (language == EShLangCompute) {
5117         if (id.compare(0, 17, "derivative_group_") == 0) {
5118             requireExtensions(loc, 1, &E_GL_NV_compute_shader_derivatives, "compute shader derivatives");
5119             if (id == "derivative_group_quadsnv") {
5120                 publicType.shaderQualifiers.layoutDerivativeGroupQuads = true;
5121                 return;
5122             } else if (id == "derivative_group_linearnv") {
5123                 publicType.shaderQualifiers.layoutDerivativeGroupLinear = true;
5124                 return;
5125             }
5126         }
5127     }
5128 #endif
5129 
5130     error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), "");
5131 }
5132 
5133 // Put the id's layout qualifier value into the public type, for qualifiers having a number set.
5134 // This is before we know any type information for error checking.
setLayoutQualifier(const TSourceLoc & loc,TPublicType & publicType,TString & id,const TIntermTyped * node)5135 void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publicType, TString& id, const TIntermTyped* node)
5136 {
5137     const char* feature = "layout-id value";
5138     const char* nonLiteralFeature = "non-literal layout-id value";
5139 
5140     integerCheck(node, feature);
5141     const TIntermConstantUnion* constUnion = node->getAsConstantUnion();
5142     int value;
5143     bool nonLiteral = false;
5144     if (constUnion) {
5145         value = constUnion->getConstArray()[0].getIConst();
5146         if (! constUnion->isLiteral()) {
5147             requireProfile(loc, ECoreProfile | ECompatibilityProfile, nonLiteralFeature);
5148             profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, nonLiteralFeature);
5149         }
5150     } else {
5151         // grammar should have give out the error message
5152         value = 0;
5153         nonLiteral = true;
5154     }
5155 
5156     if (value < 0) {
5157         error(loc, "cannot be negative", feature, "");
5158         return;
5159     }
5160 
5161     std::transform(id.begin(), id.end(), id.begin(), ::tolower);
5162 
5163     if (id == "offset") {
5164         // "offset" can be for either
5165         //  - uniform offsets
5166         //  - atomic_uint offsets
5167         const char* feature = "offset";
5168         if (spvVersion.spv == 0) {
5169             requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature);
5170             const char* exts[2] = { E_GL_ARB_enhanced_layouts, E_GL_ARB_shader_atomic_counters };
5171             profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, 2, exts, feature);
5172             profileRequires(loc, EEsProfile, 310, nullptr, feature);
5173         }
5174         publicType.qualifier.layoutOffset = value;
5175         publicType.qualifier.explicitOffset = true;
5176         if (nonLiteral)
5177             error(loc, "needs a literal integer", "offset", "");
5178         return;
5179     } else if (id == "align") {
5180         const char* feature = "uniform buffer-member align";
5181         if (spvVersion.spv == 0) {
5182             requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
5183             profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature);
5184         }
5185         // "The specified alignment must be a power of 2, or a compile-time error results."
5186         if (! IsPow2(value))
5187             error(loc, "must be a power of 2", "align", "");
5188         else
5189             publicType.qualifier.layoutAlign = value;
5190         if (nonLiteral)
5191             error(loc, "needs a literal integer", "align", "");
5192         return;
5193     } else if (id == "location") {
5194         profileRequires(loc, EEsProfile, 300, nullptr, "location");
5195         const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location };
5196         // GL_ARB_explicit_uniform_location requires 330 or GL_ARB_explicit_attrib_location we do not need to add it here
5197         profileRequires(loc, ~EEsProfile, 330, 2, exts, "location");
5198         if ((unsigned int)value >= TQualifier::layoutLocationEnd)
5199             error(loc, "location is too large", id.c_str(), "");
5200         else
5201             publicType.qualifier.layoutLocation = value;
5202         if (nonLiteral)
5203             error(loc, "needs a literal integer", "location", "");
5204         return;
5205     } else if (id == "set") {
5206         if ((unsigned int)value >= TQualifier::layoutSetEnd)
5207             error(loc, "set is too large", id.c_str(), "");
5208         else
5209             publicType.qualifier.layoutSet = value;
5210         if (value != 0)
5211             requireVulkan(loc, "descriptor set");
5212         if (nonLiteral)
5213             error(loc, "needs a literal integer", "set", "");
5214         return;
5215     } else if (id == "binding") {
5216 #ifndef GLSLANG_WEB
5217         profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, "binding");
5218         profileRequires(loc, EEsProfile, 310, nullptr, "binding");
5219 #endif
5220         if ((unsigned int)value >= TQualifier::layoutBindingEnd)
5221             error(loc, "binding is too large", id.c_str(), "");
5222         else
5223             publicType.qualifier.layoutBinding = value;
5224         if (nonLiteral)
5225             error(loc, "needs a literal integer", "binding", "");
5226         return;
5227     }
5228     if (id == "constant_id") {
5229         requireSpv(loc, "constant_id");
5230         if (value >= (int)TQualifier::layoutSpecConstantIdEnd) {
5231             error(loc, "specialization-constant id is too large", id.c_str(), "");
5232         } else {
5233             publicType.qualifier.layoutSpecConstantId = value;
5234             publicType.qualifier.specConstant = true;
5235             if (! intermediate.addUsedConstantId(value))
5236                 error(loc, "specialization-constant id already used", id.c_str(), "");
5237         }
5238         if (nonLiteral)
5239             error(loc, "needs a literal integer", "constant_id", "");
5240         return;
5241     }
5242 #ifndef GLSLANG_WEB
5243     if (id == "component") {
5244         requireProfile(loc, ECoreProfile | ECompatibilityProfile, "component");
5245         profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, "component");
5246         if ((unsigned)value >= TQualifier::layoutComponentEnd)
5247             error(loc, "component is too large", id.c_str(), "");
5248         else
5249             publicType.qualifier.layoutComponent = value;
5250         if (nonLiteral)
5251             error(loc, "needs a literal integer", "component", "");
5252         return;
5253     }
5254     if (id.compare(0, 4, "xfb_") == 0) {
5255         // "Any shader making any static use (after preprocessing) of any of these
5256         // *xfb_* qualifiers will cause the shader to be in a transform feedback
5257         // capturing mode and hence responsible for describing the transform feedback
5258         // setup."
5259         intermediate.setXfbMode();
5260         const char* feature = "transform feedback qualifier";
5261         requireStage(loc, (EShLanguageMask)(EShLangVertexMask | EShLangGeometryMask | EShLangTessControlMask | EShLangTessEvaluationMask), feature);
5262         requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
5263         profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature);
5264         if (id == "xfb_buffer") {
5265             // "It is a compile-time error to specify an *xfb_buffer* that is greater than
5266             // the implementation-dependent constant gl_MaxTransformFeedbackBuffers."
5267             if (value >= resources.maxTransformFeedbackBuffers)
5268                 error(loc, "buffer is too large:", id.c_str(), "gl_MaxTransformFeedbackBuffers is %d", resources.maxTransformFeedbackBuffers);
5269             if (value >= (int)TQualifier::layoutXfbBufferEnd)
5270                 error(loc, "buffer is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbBufferEnd-1);
5271             else
5272                 publicType.qualifier.layoutXfbBuffer = value;
5273             if (nonLiteral)
5274                 error(loc, "needs a literal integer", "xfb_buffer", "");
5275             return;
5276         } else if (id == "xfb_offset") {
5277             if (value >= (int)TQualifier::layoutXfbOffsetEnd)
5278                 error(loc, "offset is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbOffsetEnd-1);
5279             else
5280                 publicType.qualifier.layoutXfbOffset = value;
5281             if (nonLiteral)
5282                 error(loc, "needs a literal integer", "xfb_offset", "");
5283             return;
5284         } else if (id == "xfb_stride") {
5285             // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the
5286             // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents."
5287             if (value > 4 * resources.maxTransformFeedbackInterleavedComponents) {
5288                 error(loc, "1/4 stride is too large:", id.c_str(), "gl_MaxTransformFeedbackInterleavedComponents is %d",
5289                     resources.maxTransformFeedbackInterleavedComponents);
5290             }
5291             if (value >= (int)TQualifier::layoutXfbStrideEnd)
5292                 error(loc, "stride is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbStrideEnd-1);
5293             else
5294                 publicType.qualifier.layoutXfbStride = value;
5295             if (nonLiteral)
5296                 error(loc, "needs a literal integer", "xfb_stride", "");
5297             return;
5298         }
5299     }
5300     if (id == "input_attachment_index") {
5301         requireVulkan(loc, "input_attachment_index");
5302         if (value >= (int)TQualifier::layoutAttachmentEnd)
5303             error(loc, "attachment index is too large", id.c_str(), "");
5304         else
5305             publicType.qualifier.layoutAttachment = value;
5306         if (nonLiteral)
5307             error(loc, "needs a literal integer", "input_attachment_index", "");
5308         return;
5309     }
5310     if (id == "num_views") {
5311         requireExtensions(loc, Num_OVR_multiview_EXTs, OVR_multiview_EXTs, "num_views");
5312         publicType.shaderQualifiers.numViews = value;
5313         if (nonLiteral)
5314             error(loc, "needs a literal integer", "num_views", "");
5315         return;
5316     }
5317     if (language == EShLangVertex ||
5318         language == EShLangTessControl ||
5319         language == EShLangTessEvaluation ||
5320         language == EShLangGeometry) {
5321         if (id == "secondary_view_offset") {
5322             requireExtensions(loc, 1, &E_GL_NV_stereo_view_rendering, "stereo view rendering");
5323             publicType.qualifier.layoutSecondaryViewportRelativeOffset = value;
5324             if (nonLiteral)
5325                 error(loc, "needs a literal integer", "secondary_view_offset", "");
5326             return;
5327         }
5328     }
5329 
5330     if (id == "buffer_reference_align") {
5331         requireExtensions(loc, 1, &E_GL_EXT_buffer_reference, "buffer_reference_align");
5332         if (! IsPow2(value))
5333             error(loc, "must be a power of 2", "buffer_reference_align", "");
5334         else
5335             publicType.qualifier.layoutBufferReferenceAlign = (unsigned int)std::log2(value);
5336         if (nonLiteral)
5337             error(loc, "needs a literal integer", "buffer_reference_align", "");
5338         return;
5339     }
5340 #endif
5341 
5342     switch (language) {
5343 #ifndef GLSLANG_WEB
5344     case EShLangTessControl:
5345         if (id == "vertices") {
5346             if (value == 0)
5347                 error(loc, "must be greater than 0", "vertices", "");
5348             else
5349                 publicType.shaderQualifiers.vertices = value;
5350             if (nonLiteral)
5351                 error(loc, "needs a literal integer", "vertices", "");
5352             return;
5353         }
5354         break;
5355 
5356     case EShLangGeometry:
5357         if (id == "invocations") {
5358             profileRequires(loc, ECompatibilityProfile | ECoreProfile, 400, nullptr, "invocations");
5359             if (value == 0)
5360                 error(loc, "must be at least 1", "invocations", "");
5361             else
5362                 publicType.shaderQualifiers.invocations = value;
5363             if (nonLiteral)
5364                 error(loc, "needs a literal integer", "invocations", "");
5365             return;
5366         }
5367         if (id == "max_vertices") {
5368             publicType.shaderQualifiers.vertices = value;
5369             if (value > resources.maxGeometryOutputVertices)
5370                 error(loc, "too large, must be less than gl_MaxGeometryOutputVertices", "max_vertices", "");
5371             if (nonLiteral)
5372                 error(loc, "needs a literal integer", "max_vertices", "");
5373             return;
5374         }
5375         if (id == "stream") {
5376             requireProfile(loc, ~EEsProfile, "selecting output stream");
5377             publicType.qualifier.layoutStream = value;
5378             if (value > 0)
5379                 intermediate.setMultiStream();
5380             if (nonLiteral)
5381                 error(loc, "needs a literal integer", "stream", "");
5382             return;
5383         }
5384         break;
5385 
5386     case EShLangFragment:
5387         if (id == "index") {
5388             requireProfile(loc, ECompatibilityProfile | ECoreProfile, "index layout qualifier on fragment output");
5389             const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location };
5390             profileRequires(loc, ECompatibilityProfile | ECoreProfile, 330, 2, exts, "index layout qualifier on fragment output");
5391 
5392             // "It is also a compile-time error if a fragment shader sets a layout index to less than 0 or greater than 1."
5393             if (value < 0 || value > 1) {
5394                 value = 0;
5395                 error(loc, "value must be 0 or 1", "index", "");
5396             }
5397 
5398             publicType.qualifier.layoutIndex = value;
5399             if (nonLiteral)
5400                 error(loc, "needs a literal integer", "index", "");
5401             return;
5402         }
5403         break;
5404 
5405     case EShLangMeshNV:
5406         if (id == "max_vertices") {
5407             requireExtensions(loc, 1, &E_GL_NV_mesh_shader, "max_vertices");
5408             publicType.shaderQualifiers.vertices = value;
5409             if (value > resources.maxMeshOutputVerticesNV)
5410                 error(loc, "too large, must be less than gl_MaxMeshOutputVerticesNV", "max_vertices", "");
5411             if (nonLiteral)
5412                 error(loc, "needs a literal integer", "max_vertices", "");
5413             return;
5414         }
5415         if (id == "max_primitives") {
5416             requireExtensions(loc, 1, &E_GL_NV_mesh_shader, "max_primitives");
5417             publicType.shaderQualifiers.primitives = value;
5418             if (value > resources.maxMeshOutputPrimitivesNV)
5419                 error(loc, "too large, must be less than gl_MaxMeshOutputPrimitivesNV", "max_primitives", "");
5420             if (nonLiteral)
5421                 error(loc, "needs a literal integer", "max_primitives", "");
5422             return;
5423         }
5424         // Fall through
5425 
5426     case EShLangTaskNV:
5427         // Fall through
5428 #endif
5429     case EShLangCompute:
5430         if (id.compare(0, 11, "local_size_") == 0) {
5431 #ifndef GLSLANG_WEB
5432             if (language == EShLangMeshNV || language == EShLangTaskNV) {
5433                 requireExtensions(loc, 1, &E_GL_NV_mesh_shader, "gl_WorkGroupSize");
5434             } else {
5435                 profileRequires(loc, EEsProfile, 310, 0, "gl_WorkGroupSize");
5436                 profileRequires(loc, ~EEsProfile, 430, E_GL_ARB_compute_shader, "gl_WorkGroupSize");
5437             }
5438 #endif
5439             if (nonLiteral)
5440                 error(loc, "needs a literal integer", "local_size", "");
5441             if (id.size() == 12 && value == 0) {
5442                 error(loc, "must be at least 1", id.c_str(), "");
5443                 return;
5444             }
5445             if (id == "local_size_x") {
5446                 publicType.shaderQualifiers.localSize[0] = value;
5447                 publicType.shaderQualifiers.localSizeNotDefault[0] = true;
5448                 return;
5449             }
5450             if (id == "local_size_y") {
5451                 publicType.shaderQualifiers.localSize[1] = value;
5452                 publicType.shaderQualifiers.localSizeNotDefault[1] = true;
5453                 return;
5454             }
5455             if (id == "local_size_z") {
5456                 publicType.shaderQualifiers.localSize[2] = value;
5457                 publicType.shaderQualifiers.localSizeNotDefault[2] = true;
5458                 return;
5459             }
5460             if (spvVersion.spv != 0) {
5461                 if (id == "local_size_x_id") {
5462                     publicType.shaderQualifiers.localSizeSpecId[0] = value;
5463                     return;
5464                 }
5465                 if (id == "local_size_y_id") {
5466                     publicType.shaderQualifiers.localSizeSpecId[1] = value;
5467                     return;
5468                 }
5469                 if (id == "local_size_z_id") {
5470                     publicType.shaderQualifiers.localSizeSpecId[2] = value;
5471                     return;
5472                 }
5473             }
5474         }
5475         break;
5476 
5477     default:
5478         break;
5479     }
5480 
5481     error(loc, "there is no such layout identifier for this stage taking an assigned value", id.c_str(), "");
5482 }
5483 
5484 // Merge any layout qualifier information from src into dst, leaving everything else in dst alone
5485 //
5486 // "More than one layout qualifier may appear in a single declaration.
5487 // Additionally, the same layout-qualifier-name can occur multiple times
5488 // within a layout qualifier or across multiple layout qualifiers in the
5489 // same declaration. When the same layout-qualifier-name occurs
5490 // multiple times, in a single declaration, the last occurrence overrides
5491 // the former occurrence(s).  Further, if such a layout-qualifier-name
5492 // will effect subsequent declarations or other observable behavior, it
5493 // is only the last occurrence that will have any effect, behaving as if
5494 // the earlier occurrence(s) within the declaration are not present.
5495 // This is also true for overriding layout-qualifier-names, where one
5496 // overrides the other (e.g., row_major vs. column_major); only the last
5497 // occurrence has any effect."
mergeObjectLayoutQualifiers(TQualifier & dst,const TQualifier & src,bool inheritOnly)5498 void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifier& src, bool inheritOnly)
5499 {
5500     if (src.hasMatrix())
5501         dst.layoutMatrix = src.layoutMatrix;
5502     if (src.hasPacking())
5503         dst.layoutPacking = src.layoutPacking;
5504 
5505 #ifndef GLSLANG_WEB
5506     if (src.hasStream())
5507         dst.layoutStream = src.layoutStream;
5508     if (src.hasFormat())
5509         dst.layoutFormat = src.layoutFormat;
5510     if (src.hasXfbBuffer())
5511         dst.layoutXfbBuffer = src.layoutXfbBuffer;
5512     if (src.hasBufferReferenceAlign())
5513         dst.layoutBufferReferenceAlign = src.layoutBufferReferenceAlign;
5514 #endif
5515 
5516     if (src.hasAlign())
5517         dst.layoutAlign = src.layoutAlign;
5518 
5519     if (! inheritOnly) {
5520         if (src.hasLocation())
5521             dst.layoutLocation = src.layoutLocation;
5522         if (src.hasOffset())
5523             dst.layoutOffset = src.layoutOffset;
5524         if (src.hasSet())
5525             dst.layoutSet = src.layoutSet;
5526         if (src.layoutBinding != TQualifier::layoutBindingEnd)
5527             dst.layoutBinding = src.layoutBinding;
5528 
5529         if (src.hasSpecConstantId())
5530             dst.layoutSpecConstantId = src.layoutSpecConstantId;
5531 
5532 #ifndef GLSLANG_WEB
5533         if (src.hasComponent())
5534             dst.layoutComponent = src.layoutComponent;
5535         if (src.hasIndex())
5536             dst.layoutIndex = src.layoutIndex;
5537         if (src.hasXfbStride())
5538             dst.layoutXfbStride = src.layoutXfbStride;
5539         if (src.hasXfbOffset())
5540             dst.layoutXfbOffset = src.layoutXfbOffset;
5541         if (src.hasAttachment())
5542             dst.layoutAttachment = src.layoutAttachment;
5543         if (src.layoutPushConstant)
5544             dst.layoutPushConstant = true;
5545 
5546         if (src.layoutBufferReference)
5547             dst.layoutBufferReference = true;
5548 
5549         if (src.layoutPassthrough)
5550             dst.layoutPassthrough = true;
5551         if (src.layoutViewportRelative)
5552             dst.layoutViewportRelative = true;
5553         if (src.layoutSecondaryViewportRelativeOffset != -2048)
5554             dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset;
5555         if (src.layoutShaderRecord)
5556             dst.layoutShaderRecord = true;
5557         if (src.pervertexNV)
5558             dst.pervertexNV = true;
5559 #endif
5560     }
5561 }
5562 
5563 // Do error layout error checking given a full variable/block declaration.
layoutObjectCheck(const TSourceLoc & loc,const TSymbol & symbol)5564 void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symbol)
5565 {
5566     const TType& type = symbol.getType();
5567     const TQualifier& qualifier = type.getQualifier();
5568 
5569     // first, cross check WRT to just the type
5570     layoutTypeCheck(loc, type);
5571 
5572     // now, any remaining error checking based on the object itself
5573 
5574     if (qualifier.hasAnyLocation()) {
5575         switch (qualifier.storage) {
5576         case EvqUniform:
5577         case EvqBuffer:
5578             if (symbol.getAsVariable() == nullptr)
5579                 error(loc, "can only be used on variable declaration", "location", "");
5580             break;
5581         default:
5582             break;
5583         }
5584     }
5585 
5586     // user-variable location check, which are required for SPIR-V in/out:
5587     //  - variables have it directly,
5588     //  - blocks have it on each member (already enforced), so check first one
5589     if (spvVersion.spv > 0 && !parsingBuiltins && qualifier.builtIn == EbvNone &&
5590         !qualifier.hasLocation() && !intermediate.getAutoMapLocations()) {
5591 
5592         switch (qualifier.storage) {
5593         case EvqVaryingIn:
5594         case EvqVaryingOut:
5595             if (!type.getQualifier().isTaskMemory() &&
5596                 (type.getBasicType() != EbtBlock ||
5597                  (!(*type.getStruct())[0].type->getQualifier().hasLocation() &&
5598                    (*type.getStruct())[0].type->getQualifier().builtIn == EbvNone)))
5599                 error(loc, "SPIR-V requires location for user input/output", "location", "");
5600             break;
5601         default:
5602             break;
5603         }
5604     }
5605 
5606     // Check packing and matrix
5607     if (qualifier.hasUniformLayout()) {
5608         switch (qualifier.storage) {
5609         case EvqUniform:
5610         case EvqBuffer:
5611             if (type.getBasicType() != EbtBlock) {
5612                 if (qualifier.hasMatrix())
5613                     error(loc, "cannot specify matrix layout on a variable declaration", "layout", "");
5614                 if (qualifier.hasPacking())
5615                     error(loc, "cannot specify packing on a variable declaration", "layout", "");
5616                 // "The offset qualifier can only be used on block members of blocks..."
5617                 if (qualifier.hasOffset() && !type.isAtomic())
5618                     error(loc, "cannot specify on a variable declaration", "offset", "");
5619                 // "The align qualifier can only be used on blocks or block members..."
5620                 if (qualifier.hasAlign())
5621                     error(loc, "cannot specify on a variable declaration", "align", "");
5622                 if (qualifier.isPushConstant())
5623                     error(loc, "can only specify on a uniform block", "push_constant", "");
5624                 if (qualifier.isShaderRecord())
5625                     error(loc, "can only specify on a buffer block", "shaderRecordNV", "");
5626             }
5627             break;
5628         default:
5629             // these were already filtered by layoutTypeCheck() (or its callees)
5630             break;
5631         }
5632     }
5633 }
5634 
5635 // "For some blocks declared as arrays, the location can only be applied at the block level:
5636 // When a block is declared as an array where additional locations are needed for each member
5637 // for each block array element, it is a compile-time error to specify locations on the block
5638 // members.  That is, when locations would be under specified by applying them on block members,
5639 // they are not allowed on block members.  For arrayed interfaces (those generally having an
5640 // extra level of arrayness due to interface expansion), the outer array is stripped before
5641 // applying this rule."
layoutMemberLocationArrayCheck(const TSourceLoc & loc,bool memberWithLocation,TArraySizes * arraySizes)5642 void TParseContext::layoutMemberLocationArrayCheck(const TSourceLoc& loc, bool memberWithLocation,
5643     TArraySizes* arraySizes)
5644 {
5645     if (memberWithLocation && arraySizes != nullptr) {
5646         if (arraySizes->getNumDims() > (currentBlockQualifier.isArrayedIo(language) ? 1 : 0))
5647             error(loc, "cannot use in a block array where new locations are needed for each block element",
5648                        "location", "");
5649     }
5650 }
5651 
5652 // Do layout error checking with respect to a type.
layoutTypeCheck(const TSourceLoc & loc,const TType & type)5653 void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
5654 {
5655     const TQualifier& qualifier = type.getQualifier();
5656 
5657     // first, intra-layout qualifier-only error checking
5658     layoutQualifierCheck(loc, qualifier);
5659 
5660     // now, error checking combining type and qualifier
5661 
5662     if (qualifier.hasAnyLocation()) {
5663         if (qualifier.hasLocation()) {
5664             if (qualifier.storage == EvqVaryingOut && language == EShLangFragment) {
5665                 if (qualifier.layoutLocation >= (unsigned int)resources.maxDrawBuffers)
5666                     error(loc, "too large for fragment output", "location", "");
5667             }
5668         }
5669         if (qualifier.hasComponent()) {
5670             // "It is a compile-time error if this sequence of components gets larger than 3."
5671             if (qualifier.layoutComponent + type.getVectorSize() * (type.getBasicType() == EbtDouble ? 2 : 1) > 4)
5672                 error(loc, "type overflows the available 4 components", "component", "");
5673 
5674             // "It is a compile-time error to apply the component qualifier to a matrix, a structure, a block, or an array containing any of these."
5675             if (type.isMatrix() || type.getBasicType() == EbtBlock || type.getBasicType() == EbtStruct)
5676                 error(loc, "cannot apply to a matrix, structure, or block", "component", "");
5677 
5678             // " It is a compile-time error to use component 1 or 3 as the beginning of a double or dvec2."
5679             if (type.getBasicType() == EbtDouble)
5680                 if (qualifier.layoutComponent & 1)
5681                     error(loc, "doubles cannot start on an odd-numbered component", "component", "");
5682         }
5683 
5684         switch (qualifier.storage) {
5685         case EvqVaryingIn:
5686         case EvqVaryingOut:
5687             if (type.getBasicType() == EbtBlock)
5688                 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, "location qualifier on in/out block");
5689             if (type.getQualifier().isTaskMemory())
5690                 error(loc, "cannot apply to taskNV in/out blocks", "location", "");
5691             break;
5692         case EvqUniform:
5693         case EvqBuffer:
5694             if (type.getBasicType() == EbtBlock)
5695                 error(loc, "cannot apply to uniform or buffer block", "location", "");
5696             break;
5697 #ifndef GLSLANG_WEB
5698         case EvqPayload:
5699         case EvqPayloadIn:
5700         case EvqHitAttr:
5701         case EvqCallableData:
5702         case EvqCallableDataIn:
5703             break;
5704 #endif
5705         default:
5706             error(loc, "can only apply to uniform, buffer, in, or out storage qualifiers", "location", "");
5707             break;
5708         }
5709 
5710         bool typeCollision;
5711         int repeated = intermediate.addUsedLocation(qualifier, type, typeCollision);
5712         if (repeated >= 0 && ! typeCollision)
5713             error(loc, "overlapping use of location", "location", "%d", repeated);
5714         // "fragment-shader outputs ... if two variables are placed within the same
5715         // location, they must have the same underlying type (floating-point or integer)"
5716         if (typeCollision && language == EShLangFragment && qualifier.isPipeOutput())
5717             error(loc, "fragment outputs sharing the same location must be the same basic type", "location", "%d", repeated);
5718     }
5719 
5720 #ifndef GLSLANG_WEB
5721     if (qualifier.hasXfbOffset() && qualifier.hasXfbBuffer()) {
5722         int repeated = intermediate.addXfbBufferOffset(type);
5723         if (repeated >= 0)
5724             error(loc, "overlapping offsets at", "xfb_offset", "offset %d in buffer %d", repeated, qualifier.layoutXfbBuffer);
5725 
5726         // "The offset must be a multiple of the size of the first component of the first
5727         // qualified variable or block member, or a compile-time error results. Further, if applied to an aggregate
5728         // containing a double or 64-bit integer, the offset must also be a multiple of 8..."
5729         if ((type.containsBasicType(EbtDouble) || type.containsBasicType(EbtInt64) || type.containsBasicType(EbtUint64)) &&
5730             ! IsMultipleOfPow2(qualifier.layoutXfbOffset, 8))
5731             error(loc, "type contains double or 64-bit integer; xfb_offset must be a multiple of 8", "xfb_offset", "");
5732         else if ((type.containsBasicType(EbtBool) || type.containsBasicType(EbtFloat) ||
5733                   type.containsBasicType(EbtInt) || type.containsBasicType(EbtUint)) &&
5734                  ! IsMultipleOfPow2(qualifier.layoutXfbOffset, 4))
5735             error(loc, "must be a multiple of size of first component", "xfb_offset", "");
5736         // ..., if applied to an aggregate containing a half float or 16-bit integer, the offset must also be a multiple of 2..."
5737         else if ((type.contains16BitFloat() || type.containsBasicType(EbtInt16) || type.containsBasicType(EbtUint16)) &&
5738                  !IsMultipleOfPow2(qualifier.layoutXfbOffset, 2))
5739             error(loc, "type contains half float or 16-bit integer; xfb_offset must be a multiple of 2", "xfb_offset", "");
5740     }
5741     if (qualifier.hasXfbStride() && qualifier.hasXfbBuffer()) {
5742         if (! intermediate.setXfbBufferStride(qualifier.layoutXfbBuffer, qualifier.layoutXfbStride))
5743             error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", qualifier.layoutXfbBuffer);
5744     }
5745 #endif
5746 
5747     if (qualifier.hasBinding()) {
5748         // Binding checking, from the spec:
5749         //
5750         // "If the binding point for any uniform or shader storage block instance is less than zero, or greater than or
5751         // equal to the implementation-dependent maximum number of uniform buffer bindings, a compile-time
5752         // error will occur. When the binding identifier is used with a uniform or shader storage block instanced as
5753         // an array of size N, all elements of the array from binding through binding + N - 1 must be within this
5754         // range."
5755         //
5756         if (! type.isOpaque() && type.getBasicType() != EbtBlock)
5757             error(loc, "requires block, or sampler/image, or atomic-counter type", "binding", "");
5758         if (type.getBasicType() == EbtSampler) {
5759             int lastBinding = qualifier.layoutBinding;
5760             if (type.isArray()) {
5761                 if (spvVersion.vulkan > 0)
5762                     lastBinding += 1;
5763                 else {
5764                     if (type.isSizedArray())
5765                         lastBinding += type.getCumulativeArraySize();
5766                     else {
5767                         lastBinding += 1;
5768 #ifndef GLSLANG_WEB
5769                         if (spvVersion.vulkan == 0)
5770                             warn(loc, "assuming binding count of one for compile-time checking of binding numbers for unsized array", "[]", "");
5771 #endif
5772                     }
5773                 }
5774             }
5775 #ifndef GLSLANG_WEB
5776             if (spvVersion.vulkan == 0 && lastBinding >= resources.maxCombinedTextureImageUnits)
5777                 error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : "");
5778 #endif
5779         }
5780         if (type.isAtomic()) {
5781             if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) {
5782                 error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", "");
5783                 return;
5784             }
5785         }
5786     } else if (!intermediate.getAutoMapBindings()) {
5787         // some types require bindings
5788 
5789         // atomic_uint
5790         if (type.isAtomic())
5791             error(loc, "layout(binding=X) is required", "atomic_uint", "");
5792 
5793         // SPIR-V
5794         if (spvVersion.spv > 0) {
5795             if (qualifier.isUniformOrBuffer()) {
5796                 if (type.getBasicType() == EbtBlock && !qualifier.isPushConstant() &&
5797                        !qualifier.isShaderRecord() &&
5798                        !qualifier.hasAttachment() &&
5799                        !qualifier.hasBufferReference())
5800                     error(loc, "uniform/buffer blocks require layout(binding=X)", "binding", "");
5801                 else if (spvVersion.vulkan > 0 && type.getBasicType() == EbtSampler)
5802                     error(loc, "sampler/texture/image requires layout(binding=X)", "binding", "");
5803             }
5804         }
5805     }
5806 
5807     // some things can't have arrays of arrays
5808     if (type.isArrayOfArrays()) {
5809         if (spvVersion.vulkan > 0) {
5810             if (type.isOpaque() || (type.getQualifier().isUniformOrBuffer() && type.getBasicType() == EbtBlock))
5811                 warn(loc, "Generating SPIR-V array-of-arrays, but Vulkan only supports single array level for this resource", "[][]", "");
5812         }
5813     }
5814 
5815     // "The offset qualifier can only be used on block members of blocks..."
5816     if (qualifier.hasOffset()) {
5817         if (type.getBasicType() == EbtBlock)
5818             error(loc, "only applies to block members, not blocks", "offset", "");
5819     }
5820 
5821     // Image format
5822     if (qualifier.hasFormat()) {
5823         if (! type.isImage())
5824             error(loc, "only apply to images", TQualifier::getLayoutFormatString(qualifier.getFormat()), "");
5825         else {
5826             if (type.getSampler().type == EbtFloat && qualifier.getFormat() > ElfFloatGuard)
5827                 error(loc, "does not apply to floating point images", TQualifier::getLayoutFormatString(qualifier.getFormat()), "");
5828             if (type.getSampler().type == EbtInt && (qualifier.getFormat() < ElfFloatGuard || qualifier.getFormat() > ElfIntGuard))
5829                 error(loc, "does not apply to signed integer images", TQualifier::getLayoutFormatString(qualifier.getFormat()), "");
5830             if (type.getSampler().type == EbtUint && qualifier.getFormat() < ElfIntGuard)
5831                 error(loc, "does not apply to unsigned integer images", TQualifier::getLayoutFormatString(qualifier.getFormat()), "");
5832 
5833             if (isEsProfile()) {
5834                 // "Except for image variables qualified with the format qualifiers r32f, r32i, and r32ui, image variables must
5835                 // specify either memory qualifier readonly or the memory qualifier writeonly."
5836                 if (! (qualifier.getFormat() == ElfR32f || qualifier.getFormat() == ElfR32i || qualifier.getFormat() == ElfR32ui)) {
5837                     if (! qualifier.isReadOnly() && ! qualifier.isWriteOnly())
5838                         error(loc, "format requires readonly or writeonly memory qualifier", TQualifier::getLayoutFormatString(qualifier.getFormat()), "");
5839                 }
5840             }
5841         }
5842     } else if (type.isImage() && ! qualifier.isWriteOnly()) {
5843         const char *explanation = "image variables not declared 'writeonly' and without a format layout qualifier";
5844         requireProfile(loc, ECoreProfile | ECompatibilityProfile, explanation);
5845         profileRequires(loc, ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shader_image_load_formatted, explanation);
5846     }
5847 
5848     if (qualifier.isPushConstant() && type.getBasicType() != EbtBlock)
5849         error(loc, "can only be used with a block", "push_constant", "");
5850 
5851     if (qualifier.hasBufferReference() && type.getBasicType() != EbtBlock)
5852         error(loc, "can only be used with a block", "buffer_reference", "");
5853 
5854     if (qualifier.isShaderRecord() && type.getBasicType() != EbtBlock)
5855         error(loc, "can only be used with a block", "shaderRecordNV", "");
5856 
5857     // input attachment
5858     if (type.isSubpass()) {
5859         if (! qualifier.hasAttachment())
5860             error(loc, "requires an input_attachment_index layout qualifier", "subpass", "");
5861     } else {
5862         if (qualifier.hasAttachment())
5863             error(loc, "can only be used with a subpass", "input_attachment_index", "");
5864     }
5865 
5866     // specialization-constant id
5867     if (qualifier.hasSpecConstantId()) {
5868         if (type.getQualifier().storage != EvqConst)
5869             error(loc, "can only be applied to 'const'-qualified scalar", "constant_id", "");
5870         if (! type.isScalar())
5871             error(loc, "can only be applied to a scalar", "constant_id", "");
5872         switch (type.getBasicType())
5873         {
5874         case EbtInt8:
5875         case EbtUint8:
5876         case EbtInt16:
5877         case EbtUint16:
5878         case EbtInt:
5879         case EbtUint:
5880         case EbtInt64:
5881         case EbtUint64:
5882         case EbtBool:
5883         case EbtFloat:
5884         case EbtDouble:
5885         case EbtFloat16:
5886             break;
5887         default:
5888             error(loc, "cannot be applied to this type", "constant_id", "");
5889             break;
5890         }
5891     }
5892 }
5893 
5894 // Do layout error checking that can be done within a layout qualifier proper, not needing to know
5895 // if there are blocks, atomic counters, variables, etc.
layoutQualifierCheck(const TSourceLoc & loc,const TQualifier & qualifier)5896 void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier)
5897 {
5898     if (qualifier.storage == EvqShared && qualifier.hasLayout())
5899         error(loc, "cannot apply layout qualifiers to a shared variable", "shared", "");
5900 
5901     // "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)."
5902     if (qualifier.hasComponent() && ! qualifier.hasLocation())
5903         error(loc, "must specify 'location' to use 'component'", "component", "");
5904 
5905     if (qualifier.hasAnyLocation()) {
5906 
5907         // "As with input layout qualifiers, all shaders except compute shaders
5908         // allow *location* layout qualifiers on output variable declarations,
5909         // output block declarations, and output block member declarations."
5910 
5911         switch (qualifier.storage) {
5912 #ifndef GLSLANG_WEB
5913         case EvqVaryingIn:
5914         {
5915             const char* feature = "location qualifier on input";
5916             if (isEsProfile() && version < 310)
5917                 requireStage(loc, EShLangVertex, feature);
5918             else
5919                 requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature);
5920             if (language == EShLangVertex) {
5921                 const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location };
5922                 profileRequires(loc, ~EEsProfile, 330, 2, exts, feature);
5923                 profileRequires(loc, EEsProfile, 300, nullptr, feature);
5924             } else {
5925                 profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature);
5926                 profileRequires(loc, EEsProfile, 310, nullptr, feature);
5927             }
5928             break;
5929         }
5930         case EvqVaryingOut:
5931         {
5932             const char* feature = "location qualifier on output";
5933             if (isEsProfile() && version < 310)
5934                 requireStage(loc, EShLangFragment, feature);
5935             else
5936                 requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature);
5937             if (language == EShLangFragment) {
5938                 const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location };
5939                 profileRequires(loc, ~EEsProfile, 330, 2, exts, feature);
5940                 profileRequires(loc, EEsProfile, 300, nullptr, feature);
5941             } else {
5942                 profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature);
5943                 profileRequires(loc, EEsProfile, 310, nullptr, feature);
5944             }
5945             break;
5946         }
5947 #endif
5948         case EvqUniform:
5949         case EvqBuffer:
5950         {
5951             const char* feature = "location qualifier on uniform or buffer";
5952             requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile | ENoProfile, feature);
5953             profileRequires(loc, ~EEsProfile, 330, E_GL_ARB_explicit_attrib_location, feature);
5954             profileRequires(loc, ~EEsProfile, 430, E_GL_ARB_explicit_uniform_location, feature);
5955             profileRequires(loc, EEsProfile, 310, nullptr, feature);
5956             break;
5957         }
5958         default:
5959             break;
5960         }
5961         if (qualifier.hasIndex()) {
5962             if (qualifier.storage != EvqVaryingOut)
5963                 error(loc, "can only be used on an output", "index", "");
5964             if (! qualifier.hasLocation())
5965                 error(loc, "can only be used with an explicit location", "index", "");
5966         }
5967     }
5968 
5969     if (qualifier.hasBinding()) {
5970         if (! qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory())
5971             error(loc, "requires uniform or buffer storage qualifier", "binding", "");
5972     }
5973     if (qualifier.hasStream()) {
5974         if (!qualifier.isPipeOutput())
5975             error(loc, "can only be used on an output", "stream", "");
5976     }
5977     if (qualifier.hasXfb()) {
5978         if (!qualifier.isPipeOutput())
5979             error(loc, "can only be used on an output", "xfb layout qualifier", "");
5980     }
5981     if (qualifier.hasUniformLayout()) {
5982         if (! qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory()) {
5983             if (qualifier.hasMatrix() || qualifier.hasPacking())
5984                 error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", "");
5985             if (qualifier.hasOffset() || qualifier.hasAlign())
5986                 error(loc, "offset/align can only be used on a uniform or buffer", "layout", "");
5987         }
5988     }
5989     if (qualifier.isPushConstant()) {
5990         if (qualifier.storage != EvqUniform)
5991             error(loc, "can only be used with a uniform", "push_constant", "");
5992         if (qualifier.hasSet())
5993             error(loc, "cannot be used with push_constant", "set", "");
5994     }
5995     if (qualifier.hasBufferReference()) {
5996         if (qualifier.storage != EvqBuffer)
5997             error(loc, "can only be used with buffer", "buffer_reference", "");
5998     }
5999     if (qualifier.isShaderRecord()) {
6000         if (qualifier.storage != EvqBuffer)
6001             error(loc, "can only be used with a buffer", "shaderRecordNV", "");
6002         if (qualifier.hasBinding())
6003             error(loc, "cannot be used with shaderRecordNV", "binding", "");
6004         if (qualifier.hasSet())
6005             error(loc, "cannot be used with shaderRecordNV", "set", "");
6006 
6007     }
6008     if (qualifier.storage == EvqHitAttr && qualifier.hasLayout()) {
6009         error(loc, "cannot apply layout qualifiers to hitAttributeNV variable", "hitAttributeNV", "");
6010     }
6011 }
6012 
6013 // For places that can't have shader-level layout qualifiers
checkNoShaderLayouts(const TSourceLoc & loc,const TShaderQualifiers & shaderQualifiers)6014 void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQualifiers& shaderQualifiers)
6015 {
6016 #ifndef GLSLANG_WEB
6017     const char* message = "can only apply to a standalone qualifier";
6018 
6019     if (shaderQualifiers.geometry != ElgNone)
6020         error(loc, message, TQualifier::getGeometryString(shaderQualifiers.geometry), "");
6021     if (shaderQualifiers.spacing != EvsNone)
6022         error(loc, message, TQualifier::getVertexSpacingString(shaderQualifiers.spacing), "");
6023     if (shaderQualifiers.order != EvoNone)
6024         error(loc, message, TQualifier::getVertexOrderString(shaderQualifiers.order), "");
6025     if (shaderQualifiers.pointMode)
6026         error(loc, message, "point_mode", "");
6027     if (shaderQualifiers.invocations != TQualifier::layoutNotSet)
6028         error(loc, message, "invocations", "");
6029     for (int i = 0; i < 3; ++i) {
6030         if (shaderQualifiers.localSize[i] > 1)
6031             error(loc, message, "local_size", "");
6032         if (shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet)
6033             error(loc, message, "local_size id", "");
6034     }
6035     if (shaderQualifiers.vertices != TQualifier::layoutNotSet) {
6036         if (language == EShLangGeometry || language == EShLangMeshNV)
6037             error(loc, message, "max_vertices", "");
6038         else if (language == EShLangTessControl)
6039             error(loc, message, "vertices", "");
6040         else
6041             assert(0);
6042     }
6043     if (shaderQualifiers.earlyFragmentTests)
6044         error(loc, message, "early_fragment_tests", "");
6045     if (shaderQualifiers.postDepthCoverage)
6046         error(loc, message, "post_depth_coverage", "");
6047     if (shaderQualifiers.primitives != TQualifier::layoutNotSet) {
6048         if (language == EShLangMeshNV)
6049             error(loc, message, "max_primitives", "");
6050         else
6051             assert(0);
6052     }
6053     if (shaderQualifiers.hasBlendEquation())
6054         error(loc, message, "blend equation", "");
6055     if (shaderQualifiers.numViews != TQualifier::layoutNotSet)
6056         error(loc, message, "num_views", "");
6057     if (shaderQualifiers.interlockOrdering != EioNone)
6058         error(loc, message, TQualifier::getInterlockOrderingString(shaderQualifiers.interlockOrdering), "");
6059 #endif
6060 }
6061 
6062 // Correct and/or advance an object's offset layout qualifier.
fixOffset(const TSourceLoc & loc,TSymbol & symbol)6063 void TParseContext::fixOffset(const TSourceLoc& loc, TSymbol& symbol)
6064 {
6065     const TQualifier& qualifier = symbol.getType().getQualifier();
6066 #ifndef GLSLANG_WEB
6067     if (symbol.getType().isAtomic()) {
6068         if (qualifier.hasBinding() && (int)qualifier.layoutBinding < resources.maxAtomicCounterBindings) {
6069 
6070             // Set the offset
6071             int offset;
6072             if (qualifier.hasOffset())
6073                 offset = qualifier.layoutOffset;
6074             else
6075                 offset = atomicUintOffsets[qualifier.layoutBinding];
6076 
6077             if (offset % 4 != 0)
6078                 error(loc, "atomic counters offset should align based on 4:", "offset", "%d", offset);
6079 
6080             symbol.getWritableType().getQualifier().layoutOffset = offset;
6081 
6082             // Check for overlap
6083             int numOffsets = 4;
6084             if (symbol.getType().isArray()) {
6085                 if (symbol.getType().isSizedArray() && !symbol.getType().getArraySizes()->isInnerUnsized())
6086                     numOffsets *= symbol.getType().getCumulativeArraySize();
6087                 else {
6088                     // "It is a compile-time error to declare an unsized array of atomic_uint."
6089                     error(loc, "array must be explicitly sized", "atomic_uint", "");
6090                 }
6091             }
6092             int repeated = intermediate.addUsedOffsets(qualifier.layoutBinding, offset, numOffsets);
6093             if (repeated >= 0)
6094                 error(loc, "atomic counters sharing the same offset:", "offset", "%d", repeated);
6095 
6096             // Bump the default offset
6097             atomicUintOffsets[qualifier.layoutBinding] = offset + numOffsets;
6098         }
6099     }
6100 #endif
6101 }
6102 
6103 //
6104 // Look up a function name in the symbol table, and make sure it is a function.
6105 //
6106 // Return the function symbol if found, otherwise nullptr.
6107 //
findFunction(const TSourceLoc & loc,const TFunction & call,bool & builtIn)6108 const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
6109 {
6110     if (symbolTable.isFunctionNameVariable(call.getName())) {
6111         error(loc, "can't use function syntax on variable", call.getName().c_str(), "");
6112         return nullptr;
6113     }
6114 
6115 #ifdef GLSLANG_WEB
6116     return findFunctionExact(loc, call, builtIn);
6117 #endif
6118 
6119     const TFunction* function = nullptr;
6120 
6121     // debugPrintfEXT has var args and is in the symbol table as "debugPrintfEXT()",
6122     // mangled to "debugPrintfEXT("
6123     if (call.getName() == "debugPrintfEXT") {
6124         TSymbol* symbol = symbolTable.find("debugPrintfEXT(", &builtIn);
6125         if (symbol)
6126             return symbol->getAsFunction();
6127     }
6128 
6129     bool explicitTypesEnabled = extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
6130                                 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8) ||
6131                                 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16) ||
6132                                 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int32) ||
6133                                 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int64) ||
6134                                 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16) ||
6135                                 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32) ||
6136                                 extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64);
6137 
6138     if (isEsProfile() || version < 120)
6139         function = findFunctionExact(loc, call, builtIn);
6140     else if (version < 400)
6141         function = extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) ? findFunction400(loc, call, builtIn) : findFunction120(loc, call, builtIn);
6142     else if (explicitTypesEnabled)
6143         function = findFunctionExplicitTypes(loc, call, builtIn);
6144     else
6145         function = findFunction400(loc, call, builtIn);
6146 
6147     return function;
6148 }
6149 
6150 // Function finding algorithm for ES and desktop 110.
findFunctionExact(const TSourceLoc & loc,const TFunction & call,bool & builtIn)6151 const TFunction* TParseContext::findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
6152 {
6153     TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn);
6154     if (symbol == nullptr) {
6155         error(loc, "no matching overloaded function found", call.getName().c_str(), "");
6156 
6157         return nullptr;
6158     }
6159 
6160     return symbol->getAsFunction();
6161 }
6162 
6163 // Function finding algorithm for desktop versions 120 through 330.
findFunction120(const TSourceLoc & loc,const TFunction & call,bool & builtIn)6164 const TFunction* TParseContext::findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
6165 {
6166     // first, look for an exact match
6167     TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn);
6168     if (symbol)
6169         return symbol->getAsFunction();
6170 
6171     // exact match not found, look through a list of overloaded functions of the same name
6172 
6173     // "If no exact match is found, then [implicit conversions] will be applied to find a match. Mismatched types
6174     // on input parameters (in or inout or default) must have a conversion from the calling argument type to the
6175     // formal parameter type. Mismatched types on output parameters (out or inout) must have a conversion
6176     // from the formal parameter type to the calling argument type.  When argument conversions are used to find
6177     // a match, it is a semantic error if there are multiple ways to apply these conversions to make the call match
6178     // more than one function."
6179 
6180     const TFunction* candidate = nullptr;
6181     TVector<const TFunction*> candidateList;
6182     symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn);
6183 
6184     for (auto it = candidateList.begin(); it != candidateList.end(); ++it) {
6185         const TFunction& function = *(*it);
6186 
6187         // to even be a potential match, number of arguments has to match
6188         if (call.getParamCount() != function.getParamCount())
6189             continue;
6190 
6191         bool possibleMatch = true;
6192         for (int i = 0; i < function.getParamCount(); ++i) {
6193             // same types is easy
6194             if (*function[i].type == *call[i].type)
6195                 continue;
6196 
6197             // We have a mismatch in type, see if it is implicitly convertible
6198 
6199             if (function[i].type->isArray() || call[i].type->isArray() ||
6200                 ! function[i].type->sameElementShape(*call[i].type))
6201                 possibleMatch = false;
6202             else {
6203                 // do direction-specific checks for conversion of basic type
6204                 if (function[i].type->getQualifier().isParamInput()) {
6205                     if (! intermediate.canImplicitlyPromote(call[i].type->getBasicType(), function[i].type->getBasicType()))
6206                         possibleMatch = false;
6207                 }
6208                 if (function[i].type->getQualifier().isParamOutput()) {
6209                     if (! intermediate.canImplicitlyPromote(function[i].type->getBasicType(), call[i].type->getBasicType()))
6210                         possibleMatch = false;
6211                 }
6212             }
6213             if (! possibleMatch)
6214                 break;
6215         }
6216         if (possibleMatch) {
6217             if (candidate) {
6218                 // our second match, meaning ambiguity
6219                 error(loc, "ambiguous function signature match: multiple signatures match under implicit type conversion", call.getName().c_str(), "");
6220             } else
6221                 candidate = &function;
6222         }
6223     }
6224 
6225     if (candidate == nullptr)
6226         error(loc, "no matching overloaded function found", call.getName().c_str(), "");
6227 
6228     return candidate;
6229 }
6230 
6231 // Function finding algorithm for desktop version 400 and above.
6232 //
6233 // "When function calls are resolved, an exact type match for all the arguments
6234 // is sought. If an exact match is found, all other functions are ignored, and
6235 // the exact match is used. If no exact match is found, then the implicit
6236 // conversions in section 4.1.10 Implicit Conversions will be applied to find
6237 // a match. Mismatched types on input parameters (in or inout or default) must
6238 // have a conversion from the calling argument type to the formal parameter type.
6239 // Mismatched types on output parameters (out or inout) must have a conversion
6240 // from the formal parameter type to the calling argument type.
6241 //
6242 // "If implicit conversions can be used to find more than one matching function,
6243 // a single best-matching function is sought. To determine a best match, the
6244 // conversions between calling argument and formal parameter types are compared
6245 // for each function argument and pair of matching functions. After these
6246 // comparisons are performed, each pair of matching functions are compared.
6247 // A function declaration A is considered a better match than function
6248 // declaration B if
6249 //
6250 //  * for at least one function argument, the conversion for that argument in A
6251 //    is better than the corresponding conversion in B; and
6252 //  * there is no function argument for which the conversion in B is better than
6253 //    the corresponding conversion in A.
6254 //
6255 // "If a single function declaration is considered a better match than every
6256 // other matching function declaration, it will be used. Otherwise, a
6257 // compile-time semantic error for an ambiguous overloaded function call occurs.
6258 //
6259 // "To determine whether the conversion for a single argument in one match is
6260 // better than that for another match, the following rules are applied, in order:
6261 //
6262 //  1. An exact match is better than a match involving any implicit conversion.
6263 //  2. A match involving an implicit conversion from float to double is better
6264 //     than a match involving any other implicit conversion.
6265 //  3. A match involving an implicit conversion from either int or uint to float
6266 //     is better than a match involving an implicit conversion from either int
6267 //     or uint to double.
6268 //
6269 // "If none of the rules above apply to a particular pair of conversions, neither
6270 // conversion is considered better than the other."
6271 //
findFunction400(const TSourceLoc & loc,const TFunction & call,bool & builtIn)6272 const TFunction* TParseContext::findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
6273 {
6274     // first, look for an exact match
6275     TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn);
6276     if (symbol)
6277         return symbol->getAsFunction();
6278 
6279     // no exact match, use the generic selector, parameterized by the GLSL rules
6280 
6281     // create list of candidates to send
6282     TVector<const TFunction*> candidateList;
6283     symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn);
6284 
6285     // can 'from' convert to 'to'?
6286     const auto convertible = [this,builtIn](const TType& from, const TType& to, TOperator, int) -> bool {
6287         if (from == to)
6288             return true;
6289         if (from.coopMatParameterOK(to))
6290             return true;
6291         // Allow a sized array to be passed through an unsized array parameter, for coopMatLoad/Store functions
6292         if (builtIn && from.isArray() && to.isUnsizedArray()) {
6293             TType fromElementType(from, 0);
6294             TType toElementType(to, 0);
6295             if (fromElementType == toElementType)
6296                 return true;
6297         }
6298         if (from.isArray() || to.isArray() || ! from.sameElementShape(to))
6299             return false;
6300         if (from.isCoopMat() && to.isCoopMat())
6301             return from.sameCoopMatBaseType(to);
6302         return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType());
6303     };
6304 
6305     // Is 'to2' a better conversion than 'to1'?
6306     // Ties should not be considered as better.
6307     // Assumes 'convertible' already said true.
6308     const auto better = [](const TType& from, const TType& to1, const TType& to2) -> bool {
6309         // 1. exact match
6310         if (from == to2)
6311             return from != to1;
6312         if (from == to1)
6313             return false;
6314 
6315         // 2. float -> double is better
6316         if (from.getBasicType() == EbtFloat) {
6317             if (to2.getBasicType() == EbtDouble && to1.getBasicType() != EbtDouble)
6318                 return true;
6319         }
6320 
6321         // 3. -> float is better than -> double
6322         return to2.getBasicType() == EbtFloat && to1.getBasicType() == EbtDouble;
6323     };
6324 
6325     // for ambiguity reporting
6326     bool tie = false;
6327 
6328     // send to the generic selector
6329     const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie);
6330 
6331     if (bestMatch == nullptr)
6332         error(loc, "no matching overloaded function found", call.getName().c_str(), "");
6333     else if (tie)
6334         error(loc, "ambiguous best function under implicit type conversion", call.getName().c_str(), "");
6335 
6336     return bestMatch;
6337 }
6338 
6339 // "To determine whether the conversion for a single argument in one match
6340 //  is better than that for another match, the conversion is assigned of the
6341 //  three ranks ordered from best to worst:
6342 //   1. Exact match: no conversion.
6343 //    2. Promotion: integral or floating-point promotion.
6344 //    3. Conversion: integral conversion, floating-point conversion,
6345 //       floating-integral conversion.
6346 //  A conversion C1 is better than a conversion C2 if the rank of C1 is
6347 //  better than the rank of C2."
findFunctionExplicitTypes(const TSourceLoc & loc,const TFunction & call,bool & builtIn)6348 const TFunction* TParseContext::findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
6349 {
6350     // first, look for an exact match
6351     TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn);
6352     if (symbol)
6353         return symbol->getAsFunction();
6354 
6355     // no exact match, use the generic selector, parameterized by the GLSL rules
6356 
6357     // create list of candidates to send
6358     TVector<const TFunction*> candidateList;
6359     symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn);
6360 
6361     // can 'from' convert to 'to'?
6362     const auto convertible = [this,builtIn](const TType& from, const TType& to, TOperator, int) -> bool {
6363         if (from == to)
6364             return true;
6365         if (from.coopMatParameterOK(to))
6366             return true;
6367         // Allow a sized array to be passed through an unsized array parameter, for coopMatLoad/Store functions
6368         if (builtIn && from.isArray() && to.isUnsizedArray()) {
6369             TType fromElementType(from, 0);
6370             TType toElementType(to, 0);
6371             if (fromElementType == toElementType)
6372                 return true;
6373         }
6374         if (from.isArray() || to.isArray() || ! from.sameElementShape(to))
6375             return false;
6376         if (from.isCoopMat() && to.isCoopMat())
6377             return from.sameCoopMatBaseType(to);
6378         return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType());
6379     };
6380 
6381     // Is 'to2' a better conversion than 'to1'?
6382     // Ties should not be considered as better.
6383     // Assumes 'convertible' already said true.
6384     const auto better = [this](const TType& from, const TType& to1, const TType& to2) -> bool {
6385         // 1. exact match
6386         if (from == to2)
6387             return from != to1;
6388         if (from == to1)
6389             return false;
6390 
6391         // 2. Promotion (integral, floating-point) is better
6392         TBasicType from_type = from.getBasicType();
6393         TBasicType to1_type = to1.getBasicType();
6394         TBasicType to2_type = to2.getBasicType();
6395         bool isPromotion1 = (intermediate.isIntegralPromotion(from_type, to1_type) ||
6396                              intermediate.isFPPromotion(from_type, to1_type));
6397         bool isPromotion2 = (intermediate.isIntegralPromotion(from_type, to2_type) ||
6398                              intermediate.isFPPromotion(from_type, to2_type));
6399         if (isPromotion2)
6400             return !isPromotion1;
6401         if(isPromotion1)
6402             return false;
6403 
6404         // 3. Conversion (integral, floating-point , floating-integral)
6405         bool isConversion1 = (intermediate.isIntegralConversion(from_type, to1_type) ||
6406                               intermediate.isFPConversion(from_type, to1_type) ||
6407                               intermediate.isFPIntegralConversion(from_type, to1_type));
6408         bool isConversion2 = (intermediate.isIntegralConversion(from_type, to2_type) ||
6409                               intermediate.isFPConversion(from_type, to2_type) ||
6410                               intermediate.isFPIntegralConversion(from_type, to2_type));
6411 
6412         return isConversion2 && !isConversion1;
6413     };
6414 
6415     // for ambiguity reporting
6416     bool tie = false;
6417 
6418     // send to the generic selector
6419     const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie);
6420 
6421     if (bestMatch == nullptr)
6422         error(loc, "no matching overloaded function found", call.getName().c_str(), "");
6423     else if (tie)
6424         error(loc, "ambiguous best function under implicit type conversion", call.getName().c_str(), "");
6425 
6426     return bestMatch;
6427 }
6428 
6429 // When a declaration includes a type, but not a variable name, it can be used
6430 // to establish defaults.
declareTypeDefaults(const TSourceLoc & loc,const TPublicType & publicType)6431 void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType& publicType)
6432 {
6433 #ifndef GLSLANG_WEB
6434     if (publicType.basicType == EbtAtomicUint && publicType.qualifier.hasBinding()) {
6435         if (publicType.qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) {
6436             error(loc, "atomic_uint binding is too large", "binding", "");
6437             return;
6438         }
6439 
6440         if(publicType.qualifier.hasOffset()) {
6441             atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset;
6442         }
6443         return;
6444     }
6445 
6446     if (publicType.qualifier.hasLayout() && !publicType.qualifier.hasBufferReference())
6447         warn(loc, "useless application of layout qualifier", "layout", "");
6448 #endif
6449 }
6450 
6451 //
6452 // Do everything necessary to handle a variable (non-block) declaration.
6453 // Either redeclaring a variable, or making a new one, updating the symbol
6454 // table, and all error checking.
6455 //
6456 // Returns a subtree node that computes an initializer, if needed.
6457 // Returns nullptr if there is no code to execute for initialization.
6458 //
6459 // 'publicType' is the type part of the declaration (to the left)
6460 // 'arraySizes' is the arrayness tagged on the identifier (to the right)
6461 //
declareVariable(const TSourceLoc & loc,TString & identifier,const TPublicType & publicType,TArraySizes * arraySizes,TIntermTyped * initializer)6462 TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& identifier, const TPublicType& publicType,
6463     TArraySizes* arraySizes, TIntermTyped* initializer)
6464 {
6465     // Make a fresh type that combines the characteristics from the individual
6466     // identifier syntax and the declaration-type syntax.
6467     TType type(publicType);
6468     type.transferArraySizes(arraySizes);
6469     type.copyArrayInnerSizes(publicType.arraySizes);
6470     arrayOfArrayVersionCheck(loc, type.getArraySizes());
6471 
6472     if (type.isCoopMat()) {
6473         intermediate.setUseVulkanMemoryModel();
6474         intermediate.setUseStorageBuffer();
6475 
6476         if (!publicType.typeParameters || publicType.typeParameters->getNumDims() != 4) {
6477             error(loc, "expected four type parameters", identifier.c_str(), "");
6478         }
6479         if (publicType.typeParameters) {
6480             if (isTypeFloat(publicType.basicType) &&
6481                 publicType.typeParameters->getDimSize(0) != 16 &&
6482                 publicType.typeParameters->getDimSize(0) != 32 &&
6483                 publicType.typeParameters->getDimSize(0) != 64) {
6484                 error(loc, "expected 16, 32, or 64 bits for first type parameter", identifier.c_str(), "");
6485             }
6486             if (isTypeInt(publicType.basicType) &&
6487                 publicType.typeParameters->getDimSize(0) != 8 &&
6488                 publicType.typeParameters->getDimSize(0) != 32) {
6489                 error(loc, "expected 8 or 32 bits for first type parameter", identifier.c_str(), "");
6490             }
6491         }
6492 
6493     } else {
6494         if (publicType.typeParameters && publicType.typeParameters->getNumDims() != 0) {
6495             error(loc, "unexpected type parameters", identifier.c_str(), "");
6496         }
6497     }
6498 
6499     if (voidErrorCheck(loc, identifier, type.getBasicType()))
6500         return nullptr;
6501 
6502     if (initializer)
6503         rValueErrorCheck(loc, "initializer", initializer);
6504     else
6505         nonInitConstCheck(loc, identifier, type);
6506 
6507     samplerCheck(loc, type, identifier, initializer);
6508     transparentOpaqueCheck(loc, type, identifier);
6509 #ifndef GLSLANG_WEB
6510     atomicUintCheck(loc, type, identifier);
6511     accStructCheck(loc, type, identifier);
6512     checkAndResizeMeshViewDim(loc, type, /*isBlockMember*/ false);
6513 #endif
6514     if (type.getQualifier().storage == EvqConst && type.containsReference()) {
6515         error(loc, "variables with reference type can't have qualifier 'const'", "qualifier", "");
6516     }
6517 
6518     if (type.getQualifier().storage != EvqUniform && type.getQualifier().storage != EvqBuffer) {
6519         if (type.contains16BitFloat())
6520             requireFloat16Arithmetic(loc, "qualifier", "float16 types can only be in uniform block or buffer storage");
6521         if (type.contains16BitInt())
6522             requireInt16Arithmetic(loc, "qualifier", "(u)int16 types can only be in uniform block or buffer storage");
6523         if (type.contains8BitInt())
6524             requireInt8Arithmetic(loc, "qualifier", "(u)int8 types can only be in uniform block or buffer storage");
6525     }
6526 
6527     if (type.getQualifier().storage == EvqShared && type.containsCoopMat())
6528         error(loc, "qualifier", "Cooperative matrix types must not be used in shared memory", "");
6529 
6530     if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
6531         error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");
6532     if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.getDepth() != EldNone)
6533         error(loc, "can only apply depth layout to gl_FragDepth", "layout qualifier", "");
6534 
6535     // Check for redeclaration of built-ins and/or attempting to declare a reserved name
6536     TSymbol* symbol = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), publicType.shaderQualifiers);
6537     if (symbol == nullptr)
6538         reservedErrorCheck(loc, identifier);
6539 
6540     inheritGlobalDefaults(type.getQualifier());
6541 
6542     // Declare the variable
6543     if (type.isArray()) {
6544         // Check that implicit sizing is only where allowed.
6545         arraySizesCheck(loc, type.getQualifier(), type.getArraySizes(), initializer, false);
6546 
6547         if (! arrayQualifierError(loc, type.getQualifier()) && ! arrayError(loc, type))
6548             declareArray(loc, identifier, type, symbol);
6549 
6550         if (initializer) {
6551             profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "initializer");
6552             profileRequires(loc, EEsProfile, 300, nullptr, "initializer");
6553         }
6554     } else {
6555         // non-array case
6556         if (symbol == nullptr)
6557             symbol = declareNonArray(loc, identifier, type);
6558         else if (type != symbol->getType())
6559             error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str());
6560     }
6561 
6562     if (symbol == nullptr)
6563         return nullptr;
6564 
6565     // Deal with initializer
6566     TIntermNode* initNode = nullptr;
6567     if (symbol != nullptr && initializer) {
6568         TVariable* variable = symbol->getAsVariable();
6569         if (! variable) {
6570             error(loc, "initializer requires a variable, not a member", identifier.c_str(), "");
6571             return nullptr;
6572         }
6573         initNode = executeInitializer(loc, initializer, variable);
6574     }
6575 
6576     // look for errors in layout qualifier use
6577     layoutObjectCheck(loc, *symbol);
6578 
6579     // fix up
6580     fixOffset(loc, *symbol);
6581 
6582     return initNode;
6583 }
6584 
6585 // Pick up global defaults from the provide global defaults into dst.
inheritGlobalDefaults(TQualifier & dst) const6586 void TParseContext::inheritGlobalDefaults(TQualifier& dst) const
6587 {
6588 #ifndef GLSLANG_WEB
6589     if (dst.storage == EvqVaryingOut) {
6590         if (! dst.hasStream() && language == EShLangGeometry)
6591             dst.layoutStream = globalOutputDefaults.layoutStream;
6592         if (! dst.hasXfbBuffer())
6593             dst.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer;
6594     }
6595 #endif
6596 }
6597 
6598 //
6599 // Make an internal-only variable whose name is for debug purposes only
6600 // and won't be searched for.  Callers will only use the return value to use
6601 // the variable, not the name to look it up.  It is okay if the name
6602 // is the same as other names; there won't be any conflict.
6603 //
makeInternalVariable(const char * name,const TType & type) const6604 TVariable* TParseContext::makeInternalVariable(const char* name, const TType& type) const
6605 {
6606     TString* nameString = NewPoolTString(name);
6607     TVariable* variable = new TVariable(nameString, type);
6608     symbolTable.makeInternalVariable(*variable);
6609 
6610     return variable;
6611 }
6612 
6613 //
6614 // Declare a non-array variable, the main point being there is no redeclaration
6615 // for resizing allowed.
6616 //
6617 // Return the successfully declared variable.
6618 //
declareNonArray(const TSourceLoc & loc,const TString & identifier,const TType & type)6619 TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, const TString& identifier, const TType& type)
6620 {
6621     // make a new variable
6622     TVariable* variable = new TVariable(&identifier, type);
6623 
6624 #ifndef GLSLANG_WEB
6625     ioArrayCheck(loc, type, identifier);
6626 #endif
6627 
6628     // add variable to symbol table
6629     if (symbolTable.insert(*variable)) {
6630         if (symbolTable.atGlobalLevel())
6631             trackLinkage(*variable);
6632         return variable;
6633     }
6634 
6635     error(loc, "redefinition", variable->getName().c_str(), "");
6636     return nullptr;
6637 }
6638 
6639 //
6640 // Handle all types of initializers from the grammar.
6641 //
6642 // Returning nullptr just means there is no code to execute to handle the
6643 // initializer, which will, for example, be the case for constant initializers.
6644 //
executeInitializer(const TSourceLoc & loc,TIntermTyped * initializer,TVariable * variable)6645 TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable)
6646 {
6647     //
6648     // Identifier must be of type constant, a global, or a temporary, and
6649     // starting at version 120, desktop allows uniforms to have initializers.
6650     //
6651     TStorageQualifier qualifier = variable->getType().getQualifier().storage;
6652     if (! (qualifier == EvqTemporary || qualifier == EvqGlobal || qualifier == EvqConst ||
6653            (qualifier == EvqUniform && !isEsProfile() && version >= 120))) {
6654         error(loc, " cannot initialize this type of qualifier ", variable->getType().getStorageQualifierString(), "");
6655         return nullptr;
6656     }
6657     arrayObjectCheck(loc, variable->getType(), "array initializer");
6658 
6659     //
6660     // If the initializer was from braces { ... }, we convert the whole subtree to a
6661     // constructor-style subtree, allowing the rest of the code to operate
6662     // identically for both kinds of initializers.
6663     //
6664     // Type can't be deduced from the initializer list, so a skeletal type to
6665     // follow has to be passed in.  Constness and specialization-constness
6666     // should be deduced bottom up, not dictated by the skeletal type.
6667     //
6668     TType skeletalType;
6669     skeletalType.shallowCopy(variable->getType());
6670     skeletalType.getQualifier().makeTemporary();
6671 #ifndef GLSLANG_WEB
6672     initializer = convertInitializerList(loc, skeletalType, initializer);
6673 #endif
6674     if (! initializer) {
6675         // error recovery; don't leave const without constant values
6676         if (qualifier == EvqConst)
6677             variable->getWritableType().getQualifier().makeTemporary();
6678         return nullptr;
6679     }
6680 
6681     // Fix outer arrayness if variable is unsized, getting size from the initializer
6682     if (initializer->getType().isSizedArray() && variable->getType().isUnsizedArray())
6683         variable->getWritableType().changeOuterArraySize(initializer->getType().getOuterArraySize());
6684 
6685     // Inner arrayness can also get set by an initializer
6686     if (initializer->getType().isArrayOfArrays() && variable->getType().isArrayOfArrays() &&
6687         initializer->getType().getArraySizes()->getNumDims() ==
6688            variable->getType().getArraySizes()->getNumDims()) {
6689         // adopt unsized sizes from the initializer's sizes
6690         for (int d = 1; d < variable->getType().getArraySizes()->getNumDims(); ++d) {
6691             if (variable->getType().getArraySizes()->getDimSize(d) == UnsizedArraySize) {
6692                 variable->getWritableType().getArraySizes()->setDimSize(d,
6693                     initializer->getType().getArraySizes()->getDimSize(d));
6694             }
6695         }
6696     }
6697 
6698     // Uniforms require a compile-time constant initializer
6699     if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) {
6700         error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
6701         variable->getWritableType().getQualifier().makeTemporary();
6702         return nullptr;
6703     }
6704     // Global consts require a constant initializer (specialization constant is okay)
6705     if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
6706         error(loc, "global const initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
6707         variable->getWritableType().getQualifier().makeTemporary();
6708         return nullptr;
6709     }
6710 
6711     // Const variables require a constant initializer, depending on version
6712     if (qualifier == EvqConst) {
6713         if (! initializer->getType().getQualifier().isConstant()) {
6714             const char* initFeature = "non-constant initializer";
6715             requireProfile(loc, ~EEsProfile, initFeature);
6716             profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
6717             variable->getWritableType().getQualifier().storage = EvqConstReadOnly;
6718             qualifier = EvqConstReadOnly;
6719         }
6720     } else {
6721         // Non-const global variables in ES need a const initializer.
6722         //
6723         // "In declarations of global variables with no storage qualifier or with a const
6724         // qualifier any initializer must be a constant expression."
6725         if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
6726             const char* initFeature = "non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)";
6727             if (isEsProfile()) {
6728                 if (relaxedErrors() && ! extensionTurnedOn(E_GL_EXT_shader_non_constant_global_initializers))
6729                     warn(loc, "not allowed in this version", initFeature, "");
6730                 else
6731                     profileRequires(loc, EEsProfile, 0, E_GL_EXT_shader_non_constant_global_initializers, initFeature);
6732             }
6733         }
6734     }
6735 
6736     if (qualifier == EvqConst || qualifier == EvqUniform) {
6737         // Compile-time tagging of the variable with its constant value...
6738 
6739         initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer);
6740         if (! initializer || ! initializer->getType().getQualifier().isConstant() || variable->getType() != initializer->getType()) {
6741             error(loc, "non-matching or non-convertible constant type for const initializer",
6742                   variable->getType().getStorageQualifierString(), "");
6743             variable->getWritableType().getQualifier().makeTemporary();
6744             return nullptr;
6745         }
6746 
6747         // We either have a folded constant in getAsConstantUnion, or we have to use
6748         // the initializer's subtree in the AST to represent the computation of a
6749         // specialization constant.
6750         assert(initializer->getAsConstantUnion() || initializer->getType().getQualifier().isSpecConstant());
6751         if (initializer->getAsConstantUnion())
6752             variable->setConstArray(initializer->getAsConstantUnion()->getConstArray());
6753         else {
6754             // It's a specialization constant.
6755             variable->getWritableType().getQualifier().makeSpecConstant();
6756 
6757             // Keep the subtree that computes the specialization constant with the variable.
6758             // Later, a symbol node will adopt the subtree from the variable.
6759             variable->setConstSubtree(initializer);
6760         }
6761     } else {
6762         // normal assigning of a value to a variable...
6763         specializationCheck(loc, initializer->getType(), "initializer");
6764         TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc);
6765         TIntermTyped* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc);
6766         if (! initNode)
6767             assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
6768 
6769         return initNode;
6770     }
6771 
6772     return nullptr;
6773 }
6774 
6775 //
6776 // Reprocess any initializer-list (the  "{ ... }" syntax) parts of the
6777 // initializer.
6778 //
6779 // Need to hierarchically assign correct types and implicit
6780 // conversions. Will do this mimicking the same process used for
6781 // creating a constructor-style initializer, ensuring we get the
6782 // same form.  However, it has to in parallel walk the 'type'
6783 // passed in, as type cannot be deduced from an initializer list.
6784 //
convertInitializerList(const TSourceLoc & loc,const TType & type,TIntermTyped * initializer)6785 TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const TType& type, TIntermTyped* initializer)
6786 {
6787     // Will operate recursively.  Once a subtree is found that is constructor style,
6788     // everything below it is already good: Only the "top part" of the initializer
6789     // can be an initializer list, where "top part" can extend for several (or all) levels.
6790 
6791     // see if we have bottomed out in the tree within the initializer-list part
6792     TIntermAggregate* initList = initializer->getAsAggregate();
6793     if (! initList || initList->getOp() != EOpNull)
6794         return initializer;
6795 
6796     // Of the initializer-list set of nodes, need to process bottom up,
6797     // so recurse deep, then process on the way up.
6798 
6799     // Go down the tree here...
6800     if (type.isArray()) {
6801         // The type's array might be unsized, which could be okay, so base sizes on the size of the aggregate.
6802         // Later on, initializer execution code will deal with array size logic.
6803         TType arrayType;
6804         arrayType.shallowCopy(type);                     // sharing struct stuff is fine
6805         arrayType.copyArraySizes(*type.getArraySizes());  // but get a fresh copy of the array information, to edit below
6806 
6807         // edit array sizes to fill in unsized dimensions
6808         arrayType.changeOuterArraySize((int)initList->getSequence().size());
6809         TIntermTyped* firstInit = initList->getSequence()[0]->getAsTyped();
6810         if (arrayType.isArrayOfArrays() && firstInit->getType().isArray() &&
6811             arrayType.getArraySizes()->getNumDims() == firstInit->getType().getArraySizes()->getNumDims() + 1) {
6812             for (int d = 1; d < arrayType.getArraySizes()->getNumDims(); ++d) {
6813                 if (arrayType.getArraySizes()->getDimSize(d) == UnsizedArraySize)
6814                     arrayType.getArraySizes()->setDimSize(d, firstInit->getType().getArraySizes()->getDimSize(d - 1));
6815             }
6816         }
6817 
6818         TType elementType(arrayType, 0); // dereferenced type
6819         for (size_t i = 0; i < initList->getSequence().size(); ++i) {
6820             initList->getSequence()[i] = convertInitializerList(loc, elementType, initList->getSequence()[i]->getAsTyped());
6821             if (initList->getSequence()[i] == nullptr)
6822                 return nullptr;
6823         }
6824 
6825         return addConstructor(loc, initList, arrayType);
6826     } else if (type.isStruct()) {
6827         if (type.getStruct()->size() != initList->getSequence().size()) {
6828             error(loc, "wrong number of structure members", "initializer list", "");
6829             return nullptr;
6830         }
6831         for (size_t i = 0; i < type.getStruct()->size(); ++i) {
6832             initList->getSequence()[i] = convertInitializerList(loc, *(*type.getStruct())[i].type, initList->getSequence()[i]->getAsTyped());
6833             if (initList->getSequence()[i] == nullptr)
6834                 return nullptr;
6835         }
6836     } else if (type.isMatrix()) {
6837         if (type.getMatrixCols() != (int)initList->getSequence().size()) {
6838             error(loc, "wrong number of matrix columns:", "initializer list", type.getCompleteString().c_str());
6839             return nullptr;
6840         }
6841         TType vectorType(type, 0); // dereferenced type
6842         for (int i = 0; i < type.getMatrixCols(); ++i) {
6843             initList->getSequence()[i] = convertInitializerList(loc, vectorType, initList->getSequence()[i]->getAsTyped());
6844             if (initList->getSequence()[i] == nullptr)
6845                 return nullptr;
6846         }
6847     } else if (type.isVector()) {
6848         if (type.getVectorSize() != (int)initList->getSequence().size()) {
6849             error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str());
6850             return nullptr;
6851         }
6852     } else {
6853         error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str());
6854         return nullptr;
6855     }
6856 
6857     // Now that the subtree is processed, process this node as if the
6858     // initializer list is a set of arguments to a constructor.
6859     TIntermNode* emulatedConstructorArguments;
6860     if (initList->getSequence().size() == 1)
6861         emulatedConstructorArguments = initList->getSequence()[0];
6862     else
6863         emulatedConstructorArguments = initList;
6864     return addConstructor(loc, emulatedConstructorArguments, type);
6865 }
6866 
6867 //
6868 // Test for the correctness of the parameters passed to various constructor functions
6869 // and also convert them to the right data type, if allowed and required.
6870 //
6871 // 'node' is what to construct from.
6872 // 'type' is what type to construct.
6873 //
6874 // Returns nullptr for an error or the constructed node (aggregate or typed) for no error.
6875 //
addConstructor(const TSourceLoc & loc,TIntermNode * node,const TType & type)6876 TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* node, const TType& type)
6877 {
6878     if (node == nullptr || node->getAsTyped() == nullptr)
6879         return nullptr;
6880     rValueErrorCheck(loc, "constructor", node->getAsTyped());
6881 
6882     TIntermAggregate* aggrNode = node->getAsAggregate();
6883     TOperator op = intermediate.mapTypeToConstructorOp(type);
6884 
6885     // Combined texture-sampler constructors are completely semantic checked
6886     // in constructorTextureSamplerError()
6887     if (op == EOpConstructTextureSampler) {
6888         if (aggrNode->getSequence()[1]->getAsTyped()->getType().getSampler().shadow) {
6889             // Transfer depth into the texture (SPIR-V image) type, as a hint
6890             // for tools to know this texture/image is a depth image.
6891             aggrNode->getSequence()[0]->getAsTyped()->getWritableType().getSampler().shadow = true;
6892         }
6893         return intermediate.setAggregateOperator(aggrNode, op, type, loc);
6894     }
6895 
6896     TTypeList::const_iterator memberTypes;
6897     if (op == EOpConstructStruct)
6898         memberTypes = type.getStruct()->begin();
6899 
6900     TType elementType;
6901     if (type.isArray()) {
6902         TType dereferenced(type, 0);
6903         elementType.shallowCopy(dereferenced);
6904     } else
6905         elementType.shallowCopy(type);
6906 
6907     bool singleArg;
6908     if (aggrNode) {
6909         if (aggrNode->getOp() != EOpNull)
6910             singleArg = true;
6911         else
6912             singleArg = false;
6913     } else
6914         singleArg = true;
6915 
6916     TIntermTyped *newNode;
6917     if (singleArg) {
6918         // If structure constructor or array constructor is being called
6919         // for only one parameter inside the structure, we need to call constructAggregate function once.
6920         if (type.isArray())
6921             newNode = constructAggregate(node, elementType, 1, node->getLoc());
6922         else if (op == EOpConstructStruct)
6923             newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc());
6924         else
6925             newNode = constructBuiltIn(type, op, node->getAsTyped(), node->getLoc(), false);
6926 
6927         if (newNode && (type.isArray() || op == EOpConstructStruct))
6928             newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc);
6929 
6930         return newNode;
6931     }
6932 
6933     //
6934     // Handle list of arguments.
6935     //
6936     TIntermSequence &sequenceVector = aggrNode->getSequence();    // Stores the information about the parameter to the constructor
6937     // if the structure constructor contains more than one parameter, then construct
6938     // each parameter
6939 
6940     int paramCount = 0;  // keeps track of the constructor parameter number being checked
6941 
6942     // for each parameter to the constructor call, check to see if the right type is passed or convert them
6943     // to the right type if possible (and allowed).
6944     // for structure constructors, just check if the right type is passed, no conversion is allowed.
6945     for (TIntermSequence::iterator p = sequenceVector.begin();
6946                                    p != sequenceVector.end(); p++, paramCount++) {
6947         if (type.isArray())
6948             newNode = constructAggregate(*p, elementType, paramCount+1, node->getLoc());
6949         else if (op == EOpConstructStruct)
6950             newNode = constructAggregate(*p, *(memberTypes[paramCount]).type, paramCount+1, node->getLoc());
6951         else
6952             newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true);
6953 
6954         if (newNode)
6955             *p = newNode;
6956         else
6957             return nullptr;
6958     }
6959 
6960     return intermediate.setAggregateOperator(aggrNode, op, type, loc);
6961 }
6962 
6963 // Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
6964 // for the parameter to the constructor (passed to this function). Essentially, it converts
6965 // the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a
6966 // float, then float is converted to int.
6967 //
6968 // Returns nullptr for an error or the constructed node.
6969 //
constructBuiltIn(const TType & type,TOperator op,TIntermTyped * node,const TSourceLoc & loc,bool subset)6970 TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, TIntermTyped* node, const TSourceLoc& loc,
6971     bool subset)
6972 {
6973     // If we are changing a matrix in both domain of basic type and to a non matrix,
6974     // do the shape change first (by default, below, basic type is changed before shape).
6975     // This avoids requesting a matrix of a new type that is going to be discarded anyway.
6976     // TODO: This could be generalized to more type combinations, but that would require
6977     // more extensive testing and full algorithm rework. For now, the need to do two changes makes
6978     // the recursive call work, and avoids the most egregious case of creating integer matrices.
6979     if (node->getType().isMatrix() && (type.isScalar() || type.isVector()) &&
6980             type.isFloatingDomain() != node->getType().isFloatingDomain()) {
6981         TType transitionType(node->getBasicType(), glslang::EvqTemporary, type.getVectorSize(), 0, 0, node->isVector());
6982         TOperator transitionOp = intermediate.mapTypeToConstructorOp(transitionType);
6983         node = constructBuiltIn(transitionType, transitionOp, node, loc, false);
6984     }
6985 
6986     TIntermTyped* newNode;
6987     TOperator basicOp;
6988 
6989     //
6990     // First, convert types as needed.
6991     //
6992     switch (op) {
6993     case EOpConstructVec2:
6994     case EOpConstructVec3:
6995     case EOpConstructVec4:
6996     case EOpConstructMat2x2:
6997     case EOpConstructMat2x3:
6998     case EOpConstructMat2x4:
6999     case EOpConstructMat3x2:
7000     case EOpConstructMat3x3:
7001     case EOpConstructMat3x4:
7002     case EOpConstructMat4x2:
7003     case EOpConstructMat4x3:
7004     case EOpConstructMat4x4:
7005     case EOpConstructFloat:
7006         basicOp = EOpConstructFloat;
7007         break;
7008 
7009     case EOpConstructIVec2:
7010     case EOpConstructIVec3:
7011     case EOpConstructIVec4:
7012     case EOpConstructInt:
7013         basicOp = EOpConstructInt;
7014         break;
7015 
7016     case EOpConstructUVec2:
7017         if (node->getType().getBasicType() == EbtReference) {
7018             requireExtensions(loc, 1, &E_GL_EXT_buffer_reference_uvec2, "reference conversion to uvec2");
7019             TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvPtrToUvec2, true, node,
7020                 type);
7021             return newNode;
7022         }
7023     case EOpConstructUVec3:
7024     case EOpConstructUVec4:
7025     case EOpConstructUint:
7026         basicOp = EOpConstructUint;
7027         break;
7028 
7029     case EOpConstructBVec2:
7030     case EOpConstructBVec3:
7031     case EOpConstructBVec4:
7032     case EOpConstructBool:
7033         basicOp = EOpConstructBool;
7034         break;
7035 
7036 #ifndef GLSLANG_WEB
7037 
7038     case EOpConstructDVec2:
7039     case EOpConstructDVec3:
7040     case EOpConstructDVec4:
7041     case EOpConstructDMat2x2:
7042     case EOpConstructDMat2x3:
7043     case EOpConstructDMat2x4:
7044     case EOpConstructDMat3x2:
7045     case EOpConstructDMat3x3:
7046     case EOpConstructDMat3x4:
7047     case EOpConstructDMat4x2:
7048     case EOpConstructDMat4x3:
7049     case EOpConstructDMat4x4:
7050     case EOpConstructDouble:
7051         basicOp = EOpConstructDouble;
7052         break;
7053 
7054     case EOpConstructF16Vec2:
7055     case EOpConstructF16Vec3:
7056     case EOpConstructF16Vec4:
7057     case EOpConstructF16Mat2x2:
7058     case EOpConstructF16Mat2x3:
7059     case EOpConstructF16Mat2x4:
7060     case EOpConstructF16Mat3x2:
7061     case EOpConstructF16Mat3x3:
7062     case EOpConstructF16Mat3x4:
7063     case EOpConstructF16Mat4x2:
7064     case EOpConstructF16Mat4x3:
7065     case EOpConstructF16Mat4x4:
7066     case EOpConstructFloat16:
7067         basicOp = EOpConstructFloat16;
7068         // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
7069         // so construct a 32-bit type and convert
7070         if (!intermediate.getArithemeticFloat16Enabled()) {
7071             TType tempType(EbtFloat, EvqTemporary, type.getVectorSize());
7072             newNode = node;
7073             if (tempType != newNode->getType()) {
7074                 TOperator aggregateOp;
7075                 if (op == EOpConstructFloat16)
7076                     aggregateOp = EOpConstructFloat;
7077                 else
7078                     aggregateOp = (TOperator)(EOpConstructVec2 + op - EOpConstructF16Vec2);
7079                 newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc());
7080             }
7081             newNode = intermediate.addConversion(EbtFloat16, newNode);
7082             return newNode;
7083         }
7084         break;
7085 
7086     case EOpConstructI8Vec2:
7087     case EOpConstructI8Vec3:
7088     case EOpConstructI8Vec4:
7089     case EOpConstructInt8:
7090         basicOp = EOpConstructInt8;
7091         // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
7092         // so construct a 32-bit type and convert
7093         if (!intermediate.getArithemeticInt8Enabled()) {
7094             TType tempType(EbtInt, EvqTemporary, type.getVectorSize());
7095             newNode = node;
7096             if (tempType != newNode->getType()) {
7097                 TOperator aggregateOp;
7098                 if (op == EOpConstructInt8)
7099                     aggregateOp = EOpConstructInt;
7100                 else
7101                     aggregateOp = (TOperator)(EOpConstructIVec2 + op - EOpConstructI8Vec2);
7102                 newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc());
7103             }
7104             newNode = intermediate.addConversion(EbtInt8, newNode);
7105             return newNode;
7106         }
7107         break;
7108 
7109     case EOpConstructU8Vec2:
7110     case EOpConstructU8Vec3:
7111     case EOpConstructU8Vec4:
7112     case EOpConstructUint8:
7113         basicOp = EOpConstructUint8;
7114         // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
7115         // so construct a 32-bit type and convert
7116         if (!intermediate.getArithemeticInt8Enabled()) {
7117             TType tempType(EbtUint, EvqTemporary, type.getVectorSize());
7118             newNode = node;
7119             if (tempType != newNode->getType()) {
7120                 TOperator aggregateOp;
7121                 if (op == EOpConstructUint8)
7122                     aggregateOp = EOpConstructUint;
7123                 else
7124                     aggregateOp = (TOperator)(EOpConstructUVec2 + op - EOpConstructU8Vec2);
7125                 newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc());
7126             }
7127             newNode = intermediate.addConversion(EbtUint8, newNode);
7128             return newNode;
7129         }
7130         break;
7131 
7132     case EOpConstructI16Vec2:
7133     case EOpConstructI16Vec3:
7134     case EOpConstructI16Vec4:
7135     case EOpConstructInt16:
7136         basicOp = EOpConstructInt16;
7137         // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
7138         // so construct a 32-bit type and convert
7139         if (!intermediate.getArithemeticInt16Enabled()) {
7140             TType tempType(EbtInt, EvqTemporary, type.getVectorSize());
7141             newNode = node;
7142             if (tempType != newNode->getType()) {
7143                 TOperator aggregateOp;
7144                 if (op == EOpConstructInt16)
7145                     aggregateOp = EOpConstructInt;
7146                 else
7147                     aggregateOp = (TOperator)(EOpConstructIVec2 + op - EOpConstructI16Vec2);
7148                 newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc());
7149             }
7150             newNode = intermediate.addConversion(EbtInt16, newNode);
7151             return newNode;
7152         }
7153         break;
7154 
7155     case EOpConstructU16Vec2:
7156     case EOpConstructU16Vec3:
7157     case EOpConstructU16Vec4:
7158     case EOpConstructUint16:
7159         basicOp = EOpConstructUint16;
7160         // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
7161         // so construct a 32-bit type and convert
7162         if (!intermediate.getArithemeticInt16Enabled()) {
7163             TType tempType(EbtUint, EvqTemporary, type.getVectorSize());
7164             newNode = node;
7165             if (tempType != newNode->getType()) {
7166                 TOperator aggregateOp;
7167                 if (op == EOpConstructUint16)
7168                     aggregateOp = EOpConstructUint;
7169                 else
7170                     aggregateOp = (TOperator)(EOpConstructUVec2 + op - EOpConstructU16Vec2);
7171                 newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc());
7172             }
7173             newNode = intermediate.addConversion(EbtUint16, newNode);
7174             return newNode;
7175         }
7176         break;
7177 
7178     case EOpConstructI64Vec2:
7179     case EOpConstructI64Vec3:
7180     case EOpConstructI64Vec4:
7181     case EOpConstructInt64:
7182         basicOp = EOpConstructInt64;
7183         break;
7184 
7185     case EOpConstructUint64:
7186         if (type.isScalar() && node->getType().isReference()) {
7187             TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvPtrToUint64, true, node, type);
7188             return newNode;
7189         }
7190         // fall through
7191     case EOpConstructU64Vec2:
7192     case EOpConstructU64Vec3:
7193     case EOpConstructU64Vec4:
7194         basicOp = EOpConstructUint64;
7195         break;
7196 
7197     case EOpConstructNonuniform:
7198         // Make a nonuniform copy of node
7199         newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpCopyObject, true, node, type);
7200         return newNode;
7201 
7202     case EOpConstructReference:
7203         // construct reference from reference
7204         if (node->getType().isReference()) {
7205             newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConstructReference, true, node, type);
7206             return newNode;
7207         // construct reference from uint64
7208         } else if (node->getType().isScalar() && node->getType().getBasicType() == EbtUint64) {
7209             TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUint64ToPtr, true, node,
7210                 type);
7211             return newNode;
7212         // construct reference from uvec2
7213         } else if (node->getType().isVector() && node->getType().getBasicType() == EbtUint &&
7214                    node->getVectorSize() == 2) {
7215             requireExtensions(loc, 1, &E_GL_EXT_buffer_reference_uvec2, "uvec2 conversion to reference");
7216             TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUvec2ToPtr, true, node,
7217                 type);
7218             return newNode;
7219         } else {
7220             return nullptr;
7221         }
7222 
7223     case EOpConstructCooperativeMatrix:
7224         if (!node->getType().isCoopMat()) {
7225             if (type.getBasicType() != node->getType().getBasicType()) {
7226                 node = intermediate.addConversion(type.getBasicType(), node);
7227             }
7228             node = intermediate.setAggregateOperator(node, EOpConstructCooperativeMatrix, type, node->getLoc());
7229         } else {
7230             TOperator op = EOpNull;
7231             switch (type.getBasicType()) {
7232             default:
7233                 assert(0);
7234                 break;
7235             case EbtInt:
7236                 switch (node->getType().getBasicType()) {
7237                     case EbtFloat:   op = EOpConvFloatToInt;    break;
7238                     case EbtFloat16: op = EOpConvFloat16ToInt;  break;
7239                     case EbtUint8:   op = EOpConvUint8ToInt;    break;
7240                     case EbtInt8:    op = EOpConvInt8ToInt;     break;
7241                     case EbtUint:    op = EOpConvUintToInt;     break;
7242                     default: assert(0);
7243                 }
7244                 break;
7245             case EbtUint:
7246                 switch (node->getType().getBasicType()) {
7247                     case EbtFloat:   op = EOpConvFloatToUint;    break;
7248                     case EbtFloat16: op = EOpConvFloat16ToUint;  break;
7249                     case EbtUint8:   op = EOpConvUint8ToUint;    break;
7250                     case EbtInt8:    op = EOpConvInt8ToUint;     break;
7251                     case EbtInt:     op = EOpConvIntToUint;      break;
7252                     case EbtUint:    op = EOpConvUintToInt8;     break;
7253                     default: assert(0);
7254                 }
7255                 break;
7256             case EbtInt8:
7257                 switch (node->getType().getBasicType()) {
7258                     case EbtFloat:   op = EOpConvFloatToInt8;    break;
7259                     case EbtFloat16: op = EOpConvFloat16ToInt8;  break;
7260                     case EbtUint8:   op = EOpConvUint8ToInt8;    break;
7261                     case EbtInt:     op = EOpConvIntToInt8;      break;
7262                     case EbtUint:    op = EOpConvUintToInt8;     break;
7263                     default: assert(0);
7264                 }
7265                 break;
7266             case EbtUint8:
7267                 switch (node->getType().getBasicType()) {
7268                     case EbtFloat:   op = EOpConvFloatToUint8;   break;
7269                     case EbtFloat16: op = EOpConvFloat16ToUint8; break;
7270                     case EbtInt8:    op = EOpConvInt8ToUint8;    break;
7271                     case EbtInt:     op = EOpConvIntToUint8;     break;
7272                     case EbtUint:    op = EOpConvUintToUint8;    break;
7273                     default: assert(0);
7274                 }
7275                 break;
7276             case EbtFloat:
7277                 switch (node->getType().getBasicType()) {
7278                     case EbtFloat16: op = EOpConvFloat16ToFloat;  break;
7279                     case EbtInt8:    op = EOpConvInt8ToFloat;     break;
7280                     case EbtUint8:   op = EOpConvUint8ToFloat;    break;
7281                     case EbtInt:     op = EOpConvIntToFloat;      break;
7282                     case EbtUint:    op = EOpConvUintToFloat;     break;
7283                     default: assert(0);
7284                 }
7285                 break;
7286             case EbtFloat16:
7287                 switch (node->getType().getBasicType()) {
7288                     case EbtFloat:  op = EOpConvFloatToFloat16;  break;
7289                     case EbtInt8:   op = EOpConvInt8ToFloat16;   break;
7290                     case EbtUint8:  op = EOpConvUint8ToFloat16;  break;
7291                     case EbtInt:    op = EOpConvIntToFloat16;    break;
7292                     case EbtUint:   op = EOpConvUintToFloat16;   break;
7293                     default: assert(0);
7294                 }
7295                 break;
7296             }
7297 
7298             node = intermediate.addUnaryNode(op, node, node->getLoc(), type);
7299             // If it's a (non-specialization) constant, it must be folded.
7300             if (node->getAsUnaryNode()->getOperand()->getAsConstantUnion())
7301                 return node->getAsUnaryNode()->getOperand()->getAsConstantUnion()->fold(op, node->getType());
7302         }
7303 
7304         return node;
7305 
7306 #endif // GLSLANG_WEB
7307 
7308     default:
7309         error(loc, "unsupported construction", "", "");
7310 
7311         return nullptr;
7312     }
7313     newNode = intermediate.addUnaryMath(basicOp, node, node->getLoc());
7314     if (newNode == nullptr) {
7315         error(loc, "can't convert", "constructor", "");
7316         return nullptr;
7317     }
7318 
7319     //
7320     // Now, if there still isn't an operation to do the construction, and we need one, add one.
7321     //
7322 
7323     // Otherwise, skip out early.
7324     if (subset || (newNode != node && newNode->getType() == type))
7325         return newNode;
7326 
7327     // setAggregateOperator will insert a new node for the constructor, as needed.
7328     return intermediate.setAggregateOperator(newNode, op, type, loc);
7329 }
7330 
7331 // This function tests for the type of the parameters to the structure or array constructor. Raises
7332 // an error message if the expected type does not match the parameter passed to the constructor.
7333 //
7334 // Returns nullptr for an error or the input node itself if the expected and the given parameter types match.
7335 //
constructAggregate(TIntermNode * node,const TType & type,int paramCount,const TSourceLoc & loc)7336 TIntermTyped* TParseContext::constructAggregate(TIntermNode* node, const TType& type, int paramCount, const TSourceLoc& loc)
7337 {
7338     TIntermTyped* converted = intermediate.addConversion(EOpConstructStruct, type, node->getAsTyped());
7339     if (! converted || converted->getType() != type) {
7340         error(loc, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
7341               node->getAsTyped()->getType().getCompleteString().c_str(), type.getCompleteString().c_str());
7342 
7343         return nullptr;
7344     }
7345 
7346     return converted;
7347 }
7348 
7349 // If a memory qualifier is present in 'to', also make it present in 'from'.
inheritMemoryQualifiers(const TQualifier & from,TQualifier & to)7350 void TParseContext::inheritMemoryQualifiers(const TQualifier& from, TQualifier& to)
7351 {
7352 #ifndef GLSLANG_WEB
7353     if (from.isReadOnly())
7354         to.readonly = from.readonly;
7355     if (from.isWriteOnly())
7356         to.writeonly = from.writeonly;
7357     if (from.coherent)
7358         to.coherent = from.coherent;
7359     if (from.volatil)
7360         to.volatil = from.volatil;
7361     if (from.restrict)
7362         to.restrict = from.restrict;
7363 #endif
7364 }
7365 
7366 //
7367 // Do everything needed to add an interface block.
7368 //
declareBlock(const TSourceLoc & loc,TTypeList & typeList,const TString * instanceName,TArraySizes * arraySizes)7369 void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, const TString* instanceName,
7370     TArraySizes* arraySizes)
7371 {
7372     blockStageIoCheck(loc, currentBlockQualifier);
7373     blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr);
7374     if (arraySizes != nullptr) {
7375         arraySizesCheck(loc, currentBlockQualifier, arraySizes, nullptr, false);
7376         arrayOfArrayVersionCheck(loc, arraySizes);
7377         if (arraySizes->getNumDims() > 1)
7378             requireProfile(loc, ~EEsProfile, "array-of-array of block");
7379     }
7380 
7381     // Inherit and check member storage qualifiers WRT to the block-level qualifier.
7382     for (unsigned int member = 0; member < typeList.size(); ++member) {
7383         TType& memberType = *typeList[member].type;
7384         TQualifier& memberQualifier = memberType.getQualifier();
7385         const TSourceLoc& memberLoc = typeList[member].loc;
7386         globalQualifierFixCheck(memberLoc, memberQualifier);
7387         if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage)
7388             error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", memberType.getFieldName().c_str(), "");
7389         memberQualifier.storage = currentBlockQualifier.storage;
7390 #ifndef GLSLANG_WEB
7391         inheritMemoryQualifiers(currentBlockQualifier, memberQualifier);
7392         if (currentBlockQualifier.perPrimitiveNV)
7393             memberQualifier.perPrimitiveNV = currentBlockQualifier.perPrimitiveNV;
7394         if (currentBlockQualifier.perViewNV)
7395             memberQualifier.perViewNV = currentBlockQualifier.perViewNV;
7396         if (currentBlockQualifier.perTaskNV)
7397             memberQualifier.perTaskNV = currentBlockQualifier.perTaskNV;
7398 #endif
7399         if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary()))
7400             error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), "");
7401         if (memberType.isArray())
7402             arraySizesCheck(memberLoc, currentBlockQualifier, memberType.getArraySizes(), nullptr, member == typeList.size() - 1);
7403         if (memberQualifier.hasOffset()) {
7404             if (spvVersion.spv == 0) {
7405                 requireProfile(memberLoc, ~EEsProfile, "offset on block member");
7406                 profileRequires(memberLoc, ~EEsProfile, 440, E_GL_ARB_enhanced_layouts, "offset on block member");
7407             }
7408         }
7409 
7410         if (memberType.containsOpaque())
7411             error(memberLoc, "member of block cannot be or contain a sampler, image, or atomic_uint type", typeList[member].type->getFieldName().c_str(), "");
7412 
7413         if (memberType.containsCoopMat())
7414             error(memberLoc, "member of block cannot be or contain a cooperative matrix type", typeList[member].type->getFieldName().c_str(), "");
7415     }
7416 
7417     // This might be a redeclaration of a built-in block.  If so, redeclareBuiltinBlock() will
7418     // do all the rest.
7419     if (! symbolTable.atBuiltInLevel() && builtInName(*blockName)) {
7420         redeclareBuiltinBlock(loc, typeList, *blockName, instanceName, arraySizes);
7421         return;
7422     }
7423 
7424     // Not a redeclaration of a built-in; check that all names are user names.
7425     reservedErrorCheck(loc, *blockName);
7426     if (instanceName)
7427         reservedErrorCheck(loc, *instanceName);
7428     for (unsigned int member = 0; member < typeList.size(); ++member)
7429         reservedErrorCheck(typeList[member].loc, typeList[member].type->getFieldName());
7430 
7431     // Make default block qualification, and adjust the member qualifications
7432 
7433     TQualifier defaultQualification;
7434     switch (currentBlockQualifier.storage) {
7435     case EvqUniform:    defaultQualification = globalUniformDefaults;    break;
7436     case EvqBuffer:     defaultQualification = globalBufferDefaults;     break;
7437     case EvqVaryingIn:  defaultQualification = globalInputDefaults;      break;
7438     case EvqVaryingOut: defaultQualification = globalOutputDefaults;     break;
7439     default:            defaultQualification.clear();                    break;
7440     }
7441 
7442     // Special case for "push_constant uniform", which has a default of std430,
7443     // contrary to normal uniform defaults, and can't have a default tracked for it.
7444     if ((currentBlockQualifier.isPushConstant() && !currentBlockQualifier.hasPacking()) ||
7445         (currentBlockQualifier.isShaderRecord() && !currentBlockQualifier.hasPacking()))
7446         currentBlockQualifier.layoutPacking = ElpStd430;
7447 
7448     // Special case for "taskNV in/out", which has a default of std430,
7449     if (currentBlockQualifier.isTaskMemory() && !currentBlockQualifier.hasPacking())
7450         currentBlockQualifier.layoutPacking = ElpStd430;
7451 
7452     // fix and check for member layout qualifiers
7453 
7454     mergeObjectLayoutQualifiers(defaultQualification, currentBlockQualifier, true);
7455 
7456     // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts."
7457     if (currentBlockQualifier.hasAlign()) {
7458         if (defaultQualification.layoutPacking != ElpStd140 &&
7459             defaultQualification.layoutPacking != ElpStd430 &&
7460             defaultQualification.layoutPacking != ElpScalar) {
7461             error(loc, "can only be used with std140, std430, or scalar layout packing", "align", "");
7462             defaultQualification.layoutAlign = -1;
7463         }
7464     }
7465 
7466     bool memberWithLocation = false;
7467     bool memberWithoutLocation = false;
7468     bool memberWithPerViewQualifier = false;
7469     for (unsigned int member = 0; member < typeList.size(); ++member) {
7470         TQualifier& memberQualifier = typeList[member].type->getQualifier();
7471         const TSourceLoc& memberLoc = typeList[member].loc;
7472 #ifndef GLSLANG_WEB
7473         if (memberQualifier.hasStream()) {
7474             if (defaultQualification.layoutStream != memberQualifier.layoutStream)
7475                 error(memberLoc, "member cannot contradict block", "stream", "");
7476         }
7477 
7478         // "This includes a block's inheritance of the
7479         // current global default buffer, a block member's inheritance of the block's
7480         // buffer, and the requirement that any *xfb_buffer* declared on a block
7481         // member must match the buffer inherited from the block."
7482         if (memberQualifier.hasXfbBuffer()) {
7483             if (defaultQualification.layoutXfbBuffer != memberQualifier.layoutXfbBuffer)
7484                 error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", "");
7485         }
7486 #endif
7487 
7488         if (memberQualifier.hasPacking())
7489             error(memberLoc, "member of block cannot have a packing layout qualifier", typeList[member].type->getFieldName().c_str(), "");
7490         if (memberQualifier.hasLocation()) {
7491             const char* feature = "location on block member";
7492             switch (currentBlockQualifier.storage) {
7493 #ifndef GLSLANG_WEB
7494             case EvqVaryingIn:
7495             case EvqVaryingOut:
7496                 requireProfile(memberLoc, ECoreProfile | ECompatibilityProfile | EEsProfile, feature);
7497                 profileRequires(memberLoc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature);
7498                 profileRequires(memberLoc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature);
7499                 memberWithLocation = true;
7500                 break;
7501 #endif
7502             default:
7503                 error(memberLoc, "can only use in an in/out block", feature, "");
7504                 break;
7505             }
7506         } else
7507             memberWithoutLocation = true;
7508 
7509         // "The offset qualifier can only be used on block members of blocks declared with std140 or std430 layouts."
7510         // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts."
7511         if (memberQualifier.hasAlign() || memberQualifier.hasOffset()) {
7512             if (defaultQualification.layoutPacking != ElpStd140 &&
7513                 defaultQualification.layoutPacking != ElpStd430 &&
7514                 defaultQualification.layoutPacking != ElpScalar)
7515                 error(memberLoc, "can only be used with std140, std430, or scalar layout packing", "offset/align", "");
7516         }
7517 
7518         if (memberQualifier.isPerView()) {
7519             memberWithPerViewQualifier = true;
7520         }
7521 
7522         TQualifier newMemberQualification = defaultQualification;
7523         mergeQualifiers(memberLoc, newMemberQualification, memberQualifier, false);
7524         memberQualifier = newMemberQualification;
7525     }
7526 
7527     layoutMemberLocationArrayCheck(loc, memberWithLocation, arraySizes);
7528 
7529 #ifndef GLSLANG_WEB
7530     // Ensure that the block has an XfbBuffer assigned. This is needed
7531     // because if the block has a XfbOffset assigned, then it is
7532     // assumed that it has implicitly assigned the current global
7533     // XfbBuffer, and because it's members need to be assigned a
7534     // XfbOffset if they lack it.
7535     if (currentBlockQualifier.storage == EvqVaryingOut && globalOutputDefaults.hasXfbBuffer()) {
7536        if (!currentBlockQualifier.hasXfbBuffer() && currentBlockQualifier.hasXfbOffset())
7537           currentBlockQualifier.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer;
7538     }
7539 #endif
7540 
7541     // Process the members
7542     fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation);
7543     fixXfbOffsets(currentBlockQualifier, typeList);
7544     fixBlockUniformOffsets(currentBlockQualifier, typeList);
7545     for (unsigned int member = 0; member < typeList.size(); ++member)
7546         layoutTypeCheck(typeList[member].loc, *typeList[member].type);
7547 
7548 #ifndef GLSLANG_WEB
7549     if (memberWithPerViewQualifier) {
7550         for (unsigned int member = 0; member < typeList.size(); ++member) {
7551             checkAndResizeMeshViewDim(typeList[member].loc, *typeList[member].type, /*isBlockMember*/ true);
7552         }
7553     }
7554 #endif
7555 
7556     // reverse merge, so that currentBlockQualifier now has all layout information
7557     // (can't use defaultQualification directly, it's missing other non-layout-default-class qualifiers)
7558     mergeObjectLayoutQualifiers(currentBlockQualifier, defaultQualification, true);
7559 
7560     //
7561     // Build and add the interface block as a new type named 'blockName'
7562     //
7563 
7564     TType blockType(&typeList, *blockName, currentBlockQualifier);
7565     if (arraySizes != nullptr)
7566         blockType.transferArraySizes(arraySizes);
7567 
7568 #ifndef GLSLANG_WEB
7569     if (arraySizes == nullptr)
7570         ioArrayCheck(loc, blockType, instanceName ? *instanceName : *blockName);
7571     if (currentBlockQualifier.hasBufferReference()) {
7572 
7573         if (currentBlockQualifier.storage != EvqBuffer)
7574             error(loc, "can only be used with buffer", "buffer_reference", "");
7575 
7576         // Create the block reference type. If it was forward-declared, detect that
7577         // as a referent struct type with no members. Replace the referent type with
7578         // blockType.
7579         TType blockNameType(EbtReference, blockType, *blockName);
7580         TVariable* blockNameVar = new TVariable(blockName, blockNameType, true);
7581         if (! symbolTable.insert(*blockNameVar)) {
7582             TSymbol* existingName = symbolTable.find(*blockName);
7583             if (existingName->getType().isReference() &&
7584                 existingName->getType().getReferentType()->getStruct() &&
7585                 existingName->getType().getReferentType()->getStruct()->size() == 0 &&
7586                 existingName->getType().getQualifier().storage == blockType.getQualifier().storage) {
7587                 existingName->getType().getReferentType()->deepCopy(blockType);
7588             } else {
7589                 error(loc, "block name cannot be redefined", blockName->c_str(), "");
7590             }
7591         }
7592         if (!instanceName) {
7593             return;
7594         }
7595     } else
7596 #endif
7597     {
7598         //
7599         // Don't make a user-defined type out of block name; that will cause an error
7600         // if the same block name gets reused in a different interface.
7601         //
7602         // "Block names have no other use within a shader
7603         // beyond interface matching; it is a compile-time error to use a block name at global scope for anything
7604         // other than as a block name (e.g., use of a block name for a global variable name or function name is
7605         // currently reserved)."
7606         //
7607         // Use the symbol table to prevent normal reuse of the block's name, as a variable entry,
7608         // whose type is EbtBlock, but without all the structure; that will come from the type
7609         // the instances point to.
7610         //
7611         TType blockNameType(EbtBlock, blockType.getQualifier().storage);
7612         TVariable* blockNameVar = new TVariable(blockName, blockNameType);
7613         if (! symbolTable.insert(*blockNameVar)) {
7614             TSymbol* existingName = symbolTable.find(*blockName);
7615             if (existingName->getType().getBasicType() == EbtBlock) {
7616                 if (existingName->getType().getQualifier().storage == blockType.getQualifier().storage) {
7617                     error(loc, "Cannot reuse block name within the same interface:", blockName->c_str(), blockType.getStorageQualifierString());
7618                     return;
7619                 }
7620             } else {
7621                 error(loc, "block name cannot redefine a non-block name", blockName->c_str(), "");
7622                 return;
7623             }
7624         }
7625     }
7626 
7627     // Add the variable, as anonymous or named instanceName.
7628     // Make an anonymous variable if no name was provided.
7629     if (! instanceName)
7630         instanceName = NewPoolTString("");
7631 
7632     TVariable& variable = *new TVariable(instanceName, blockType);
7633     if (! symbolTable.insert(variable)) {
7634         if (*instanceName == "")
7635             error(loc, "nameless block contains a member that already has a name at global scope", blockName->c_str(), "");
7636         else
7637             error(loc, "block instance name redefinition", variable.getName().c_str(), "");
7638 
7639         return;
7640     }
7641 
7642     // Check for general layout qualifier errors
7643     layoutObjectCheck(loc, variable);
7644 
7645 #ifndef GLSLANG_WEB
7646     // fix up
7647     if (isIoResizeArray(blockType)) {
7648         ioArraySymbolResizeList.push_back(&variable);
7649         checkIoArraysConsistency(loc, true);
7650     } else
7651         fixIoArraySize(loc, variable.getWritableType());
7652 #endif
7653 
7654     // Save it in the AST for linker use.
7655     trackLinkage(variable);
7656 }
7657 
7658 // Do all block-declaration checking regarding the combination of in/out/uniform/buffer
7659 // with a particular stage.
blockStageIoCheck(const TSourceLoc & loc,const TQualifier & qualifier)7660 void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier)
7661 {
7662     const char *extsrt[2] = { E_GL_NV_ray_tracing, E_GL_EXT_ray_tracing };
7663     switch (qualifier.storage) {
7664     case EvqUniform:
7665         profileRequires(loc, EEsProfile, 300, nullptr, "uniform block");
7666         profileRequires(loc, ENoProfile, 140, E_GL_ARB_uniform_buffer_object, "uniform block");
7667         if (currentBlockQualifier.layoutPacking == ElpStd430 && ! currentBlockQualifier.isPushConstant())
7668             requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "std430 requires the buffer storage qualifier");
7669         break;
7670     case EvqBuffer:
7671         requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "buffer block");
7672         profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "buffer block");
7673         profileRequires(loc, EEsProfile, 310, nullptr, "buffer block");
7674         break;
7675     case EvqVaryingIn:
7676         profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "input block");
7677         // It is a compile-time error to have an input block in a vertex shader or an output block in a fragment shader
7678         // "Compute shaders do not permit user-defined input variables..."
7679         requireStage(loc, (EShLanguageMask)(EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask|
7680             EShLangFragmentMask|EShLangMeshNVMask), "input block");
7681         if (language == EShLangFragment) {
7682             profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "fragment input block");
7683         } else if (language == EShLangMeshNV && ! qualifier.isTaskMemory()) {
7684             error(loc, "input blocks cannot be used in a mesh shader", "out", "");
7685         }
7686         break;
7687     case EvqVaryingOut:
7688         profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "output block");
7689         requireStage(loc, (EShLanguageMask)(EShLangVertexMask|EShLangTessControlMask|EShLangTessEvaluationMask|
7690             EShLangGeometryMask|EShLangMeshNVMask|EShLangTaskNVMask), "output block");
7691         // ES 310 can have a block before shader_io is turned on, so skip this test for built-ins
7692         if (language == EShLangVertex && ! parsingBuiltins) {
7693             profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "vertex output block");
7694         } else if (language == EShLangMeshNV && qualifier.isTaskMemory()) {
7695             error(loc, "can only use on input blocks in mesh shader", "taskNV", "");
7696         } else if (language == EShLangTaskNV && ! qualifier.isTaskMemory()) {
7697             error(loc, "output blocks cannot be used in a task shader", "out", "");
7698         }
7699         break;
7700 #ifndef GLSLANG_WEB
7701     case EvqPayload:
7702         profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadNV block");
7703         requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangAnyHitMask | EShLangClosestHitMask | EShLangMissMask),
7704             "rayPayloadNV block");
7705         break;
7706     case EvqPayloadIn:
7707         profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadInNV block");
7708         requireStage(loc, (EShLanguageMask)(EShLangAnyHitMask | EShLangClosestHitMask | EShLangMissMask),
7709             "rayPayloadInNV block");
7710         break;
7711     case EvqHitAttr:
7712         profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "hitAttributeNV block");
7713         requireStage(loc, (EShLanguageMask)(EShLangIntersectMask | EShLangAnyHitMask | EShLangClosestHitMask), "hitAttributeNV block");
7714         break;
7715     case EvqCallableData:
7716         profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "callableDataNV block");
7717         requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask),
7718             "callableDataNV block");
7719         break;
7720     case EvqCallableDataIn:
7721         profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "callableDataInNV block");
7722         requireStage(loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV block");
7723         break;
7724 #endif
7725     default:
7726         error(loc, "only uniform, buffer, in, or out blocks are supported", blockName->c_str(), "");
7727         break;
7728     }
7729 }
7730 
7731 // Do all block-declaration checking regarding its qualifiers.
blockQualifierCheck(const TSourceLoc & loc,const TQualifier & qualifier,bool)7732 void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier, bool /*instanceName*/)
7733 {
7734     // The 4.5 specification says:
7735     //
7736     // interface-block :
7737     //    layout-qualifieropt interface-qualifier  block-name { member-list } instance-nameopt ;
7738     //
7739     // interface-qualifier :
7740     //    in
7741     //    out
7742     //    patch in
7743     //    patch out
7744     //    uniform
7745     //    buffer
7746     //
7747     // Note however memory qualifiers aren't included, yet the specification also says
7748     //
7749     // "...memory qualifiers may also be used in the declaration of shader storage blocks..."
7750 
7751     if (qualifier.isInterpolation())
7752         error(loc, "cannot use interpolation qualifiers on an interface block", "flat/smooth/noperspective", "");
7753     if (qualifier.centroid)
7754         error(loc, "cannot use centroid qualifier on an interface block", "centroid", "");
7755     if (qualifier.isSample())
7756         error(loc, "cannot use sample qualifier on an interface block", "sample", "");
7757     if (qualifier.invariant)
7758         error(loc, "cannot use invariant qualifier on an interface block", "invariant", "");
7759     if (qualifier.isPushConstant())
7760         intermediate.addPushConstantCount();
7761     if (qualifier.isShaderRecord())
7762         intermediate.addShaderRecordCount();
7763     if (qualifier.isTaskMemory())
7764         intermediate.addTaskNVCount();
7765 }
7766 
7767 //
7768 // "For a block, this process applies to the entire block, or until the first member
7769 // is reached that has a location layout qualifier. When a block member is declared with a location
7770 // qualifier, its location comes from that qualifier: The member's location qualifier overrides the block-level
7771 // declaration. Subsequent members are again assigned consecutive locations, based on the newest location,
7772 // until the next member declared with a location qualifier. The values used for locations do not have to be
7773 // declared in increasing order."
fixBlockLocations(const TSourceLoc & loc,TQualifier & qualifier,TTypeList & typeList,bool memberWithLocation,bool memberWithoutLocation)7774 void TParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qualifier, TTypeList& typeList, bool memberWithLocation, bool memberWithoutLocation)
7775 {
7776     // "If a block has no block-level location layout qualifier, it is required that either all or none of its members
7777     // have a location layout qualifier, or a compile-time error results."
7778     if (! qualifier.hasLocation() && memberWithLocation && memberWithoutLocation)
7779         error(loc, "either the block needs a location, or all members need a location, or no members have a location", "location", "");
7780     else {
7781         if (memberWithLocation) {
7782             // remove any block-level location and make it per *every* member
7783             int nextLocation = 0;  // by the rule above, initial value is not relevant
7784             if (qualifier.hasAnyLocation()) {
7785                 nextLocation = qualifier.layoutLocation;
7786                 qualifier.layoutLocation = TQualifier::layoutLocationEnd;
7787                 if (qualifier.hasComponent()) {
7788                     // "It is a compile-time error to apply the *component* qualifier to a ... block"
7789                     error(loc, "cannot apply to a block", "component", "");
7790                 }
7791                 if (qualifier.hasIndex()) {
7792                     error(loc, "cannot apply to a block", "index", "");
7793                 }
7794             }
7795             for (unsigned int member = 0; member < typeList.size(); ++member) {
7796                 TQualifier& memberQualifier = typeList[member].type->getQualifier();
7797                 const TSourceLoc& memberLoc = typeList[member].loc;
7798                 if (! memberQualifier.hasLocation()) {
7799                     if (nextLocation >= (int)TQualifier::layoutLocationEnd)
7800                         error(memberLoc, "location is too large", "location", "");
7801                     memberQualifier.layoutLocation = nextLocation;
7802                     memberQualifier.layoutComponent = TQualifier::layoutComponentEnd;
7803                 }
7804                 nextLocation = memberQualifier.layoutLocation + intermediate.computeTypeLocationSize(
7805                                     *typeList[member].type, language);
7806             }
7807         }
7808     }
7809 }
7810 
fixXfbOffsets(TQualifier & qualifier,TTypeList & typeList)7811 void TParseContext::fixXfbOffsets(TQualifier& qualifier, TTypeList& typeList)
7812 {
7813 #ifndef GLSLANG_WEB
7814     // "If a block is qualified with xfb_offset, all its
7815     // members are assigned transform feedback buffer offsets. If a block is not qualified with xfb_offset, any
7816     // members of that block not qualified with an xfb_offset will not be assigned transform feedback buffer
7817     // offsets."
7818 
7819     if (! qualifier.hasXfbBuffer() || ! qualifier.hasXfbOffset())
7820         return;
7821 
7822     int nextOffset = qualifier.layoutXfbOffset;
7823     for (unsigned int member = 0; member < typeList.size(); ++member) {
7824         TQualifier& memberQualifier = typeList[member].type->getQualifier();
7825         bool contains64BitType = false;
7826         bool contains32BitType = false;
7827         bool contains16BitType = false;
7828         int memberSize = intermediate.computeTypeXfbSize(*typeList[member].type, contains64BitType, contains32BitType, contains16BitType);
7829         // see if we need to auto-assign an offset to this member
7830         if (! memberQualifier.hasXfbOffset()) {
7831             // "if applied to an aggregate containing a double or 64-bit integer, the offset must also be a multiple of 8"
7832             if (contains64BitType)
7833                 RoundToPow2(nextOffset, 8);
7834             else if (contains32BitType)
7835                 RoundToPow2(nextOffset, 4);
7836             else if (contains16BitType)
7837                 RoundToPow2(nextOffset, 2);
7838             memberQualifier.layoutXfbOffset = nextOffset;
7839         } else
7840             nextOffset = memberQualifier.layoutXfbOffset;
7841         nextOffset += memberSize;
7842     }
7843 
7844     // The above gave all block members an offset, so we can take it off the block now,
7845     // which will avoid double counting the offset usage.
7846     qualifier.layoutXfbOffset = TQualifier::layoutXfbOffsetEnd;
7847 #endif
7848 }
7849 
7850 // Calculate and save the offset of each block member, using the recursively
7851 // defined block offset rules and the user-provided offset and align.
7852 //
7853 // Also, compute and save the total size of the block. For the block's size, arrayness
7854 // is not taken into account, as each element is backed by a separate buffer.
7855 //
fixBlockUniformOffsets(TQualifier & qualifier,TTypeList & typeList)7856 void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typeList)
7857 {
7858     if (!qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory())
7859         return;
7860     if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar)
7861         return;
7862 
7863     int offset = 0;
7864     int memberSize;
7865     for (unsigned int member = 0; member < typeList.size(); ++member) {
7866         TQualifier& memberQualifier = typeList[member].type->getQualifier();
7867         const TSourceLoc& memberLoc = typeList[member].loc;
7868 
7869         // "When align is applied to an array, it effects only the start of the array, not the array's internal stride."
7870 
7871         // modify just the children's view of matrix layout, if there is one for this member
7872         TLayoutMatrix subMatrixLayout = typeList[member].type->getQualifier().layoutMatrix;
7873         int dummyStride;
7874         int memberAlignment = intermediate.getMemberAlignment(*typeList[member].type, memberSize, dummyStride, qualifier.layoutPacking,
7875                                                               subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : qualifier.layoutMatrix == ElmRowMajor);
7876         if (memberQualifier.hasOffset()) {
7877             // "The specified offset must be a multiple
7878             // of the base alignment of the type of the block member it qualifies, or a compile-time error results."
7879             if (! IsMultipleOfPow2(memberQualifier.layoutOffset, memberAlignment))
7880                 error(memberLoc, "must be a multiple of the member's alignment", "offset", "");
7881 
7882             // GLSL: "It is a compile-time error to specify an offset that is smaller than the offset of the previous
7883             // member in the block or that lies within the previous member of the block"
7884             if (spvVersion.spv == 0) {
7885                 if (memberQualifier.layoutOffset < offset)
7886                     error(memberLoc, "cannot lie in previous members", "offset", "");
7887 
7888                 // "The offset qualifier forces the qualified member to start at or after the specified
7889                 // integral-constant expression, which will be its byte offset from the beginning of the buffer.
7890                 // "The actual offset of a member is computed as
7891                 // follows: If offset was declared, start with that offset, otherwise start with the next available offset."
7892                 offset = std::max(offset, memberQualifier.layoutOffset);
7893             } else {
7894                 // TODO: Vulkan: "It is a compile-time error to have any offset, explicit or assigned,
7895                 // that lies within another member of the block."
7896 
7897                 offset = memberQualifier.layoutOffset;
7898             }
7899         }
7900 
7901         // "The actual alignment of a member will be the greater of the specified align alignment and the standard
7902         // (e.g., std140) base alignment for the member's type."
7903         if (memberQualifier.hasAlign())
7904             memberAlignment = std::max(memberAlignment, memberQualifier.layoutAlign);
7905 
7906         // "If the resulting offset is not a multiple of the actual alignment,
7907         // increase it to the first offset that is a multiple of
7908         // the actual alignment."
7909         RoundToPow2(offset, memberAlignment);
7910         typeList[member].type->getQualifier().layoutOffset = offset;
7911         offset += memberSize;
7912     }
7913 }
7914 
7915 // For an identifier that is already declared, add more qualification to it.
addQualifierToExisting(const TSourceLoc & loc,TQualifier qualifier,const TString & identifier)7916 void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier)
7917 {
7918     TSymbol* symbol = symbolTable.find(identifier);
7919 
7920     // A forward declaration of a block reference looks to the grammar like adding
7921     // a qualifier to an existing symbol. Detect this and create the block reference
7922     // type with an empty type list, which will be filled in later in
7923     // TParseContext::declareBlock.
7924     if (!symbol && qualifier.hasBufferReference()) {
7925         TTypeList typeList;
7926         TType blockType(&typeList, identifier, qualifier);;
7927         TType blockNameType(EbtReference, blockType, identifier);
7928         TVariable* blockNameVar = new TVariable(&identifier, blockNameType, true);
7929         if (! symbolTable.insert(*blockNameVar)) {
7930             error(loc, "block name cannot redefine a non-block name", blockName->c_str(), "");
7931         }
7932         return;
7933     }
7934 
7935     if (! symbol) {
7936         error(loc, "identifier not previously declared", identifier.c_str(), "");
7937         return;
7938     }
7939     if (symbol->getAsFunction()) {
7940         error(loc, "cannot re-qualify a function name", identifier.c_str(), "");
7941         return;
7942     }
7943 
7944     if (qualifier.isAuxiliary() ||
7945         qualifier.isMemory() ||
7946         qualifier.isInterpolation() ||
7947         qualifier.hasLayout() ||
7948         qualifier.storage != EvqTemporary ||
7949         qualifier.precision != EpqNone) {
7950         error(loc, "cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable", identifier.c_str(), "");
7951         return;
7952     }
7953 
7954     // For read-only built-ins, add a new symbol for holding the modified qualifier.
7955     // This will bring up an entire block, if a block type has to be modified (e.g., gl_Position inside a block)
7956     if (symbol->isReadOnly())
7957         symbol = symbolTable.copyUp(symbol);
7958 
7959     if (qualifier.invariant) {
7960         if (intermediate.inIoAccessed(identifier))
7961             error(loc, "cannot change qualification after use", "invariant", "");
7962         symbol->getWritableType().getQualifier().invariant = true;
7963         invariantCheck(loc, symbol->getType().getQualifier());
7964     } else if (qualifier.isNoContraction()) {
7965         if (intermediate.inIoAccessed(identifier))
7966             error(loc, "cannot change qualification after use", "precise", "");
7967         symbol->getWritableType().getQualifier().setNoContraction();
7968     } else if (qualifier.specConstant) {
7969         symbol->getWritableType().getQualifier().makeSpecConstant();
7970         if (qualifier.hasSpecConstantId())
7971             symbol->getWritableType().getQualifier().layoutSpecConstantId = qualifier.layoutSpecConstantId;
7972     } else
7973         warn(loc, "unknown requalification", "", "");
7974 }
7975 
addQualifierToExisting(const TSourceLoc & loc,TQualifier qualifier,TIdentifierList & identifiers)7976 void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, TIdentifierList& identifiers)
7977 {
7978     for (unsigned int i = 0; i < identifiers.size(); ++i)
7979         addQualifierToExisting(loc, qualifier, *identifiers[i]);
7980 }
7981 
7982 // Make sure 'invariant' isn't being applied to a non-allowed object.
invariantCheck(const TSourceLoc & loc,const TQualifier & qualifier)7983 void TParseContext::invariantCheck(const TSourceLoc& loc, const TQualifier& qualifier)
7984 {
7985     if (! qualifier.invariant)
7986         return;
7987 
7988     bool pipeOut = qualifier.isPipeOutput();
7989     bool pipeIn = qualifier.isPipeInput();
7990     if (version >= 300 || (!isEsProfile() && version >= 420)) {
7991         if (! pipeOut)
7992             error(loc, "can only apply to an output", "invariant", "");
7993     } else {
7994         if ((language == EShLangVertex && pipeIn) || (! pipeOut && ! pipeIn))
7995             error(loc, "can only apply to an output, or to an input in a non-vertex stage\n", "invariant", "");
7996     }
7997 }
7998 
7999 //
8000 // Updating default qualifier for the case of a declaration with just a qualifier,
8001 // no type, block, or identifier.
8002 //
updateStandaloneQualifierDefaults(const TSourceLoc & loc,const TPublicType & publicType)8003 void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, const TPublicType& publicType)
8004 {
8005 #ifndef GLSLANG_WEB
8006     if (publicType.shaderQualifiers.vertices != TQualifier::layoutNotSet) {
8007         assert(language == EShLangTessControl || language == EShLangGeometry || language == EShLangMeshNV);
8008         const char* id = (language == EShLangTessControl) ? "vertices" : "max_vertices";
8009 
8010         if (publicType.qualifier.storage != EvqVaryingOut)
8011             error(loc, "can only apply to 'out'", id, "");
8012         if (! intermediate.setVertices(publicType.shaderQualifiers.vertices))
8013             error(loc, "cannot change previously set layout value", id, "");
8014 
8015         if (language == EShLangTessControl)
8016             checkIoArraysConsistency(loc);
8017     }
8018     if (publicType.shaderQualifiers.primitives != TQualifier::layoutNotSet) {
8019         assert(language == EShLangMeshNV);
8020         const char* id = "max_primitives";
8021 
8022         if (publicType.qualifier.storage != EvqVaryingOut)
8023             error(loc, "can only apply to 'out'", id, "");
8024         if (! intermediate.setPrimitives(publicType.shaderQualifiers.primitives))
8025             error(loc, "cannot change previously set layout value", id, "");
8026     }
8027     if (publicType.shaderQualifiers.invocations != TQualifier::layoutNotSet) {
8028         if (publicType.qualifier.storage != EvqVaryingIn)
8029             error(loc, "can only apply to 'in'", "invocations", "");
8030         if (! intermediate.setInvocations(publicType.shaderQualifiers.invocations))
8031             error(loc, "cannot change previously set layout value", "invocations", "");
8032     }
8033     if (publicType.shaderQualifiers.geometry != ElgNone) {
8034         if (publicType.qualifier.storage == EvqVaryingIn) {
8035             switch (publicType.shaderQualifiers.geometry) {
8036             case ElgPoints:
8037             case ElgLines:
8038             case ElgLinesAdjacency:
8039             case ElgTriangles:
8040             case ElgTrianglesAdjacency:
8041             case ElgQuads:
8042             case ElgIsolines:
8043                 if (language == EShLangMeshNV) {
8044                     error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
8045                     break;
8046                 }
8047                 if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry)) {
8048                     if (language == EShLangGeometry)
8049                         checkIoArraysConsistency(loc);
8050                 } else
8051                     error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
8052                 break;
8053             default:
8054                 error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
8055             }
8056         } else if (publicType.qualifier.storage == EvqVaryingOut) {
8057             switch (publicType.shaderQualifiers.geometry) {
8058             case ElgLines:
8059             case ElgTriangles:
8060                 if (language != EShLangMeshNV) {
8061                     error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
8062                     break;
8063                 }
8064                 // Fall through
8065             case ElgPoints:
8066             case ElgLineStrip:
8067             case ElgTriangleStrip:
8068                 if (! intermediate.setOutputPrimitive(publicType.shaderQualifiers.geometry))
8069                     error(loc, "cannot change previously set output primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
8070                 break;
8071             default:
8072                 error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
8073             }
8074         } else
8075             error(loc, "cannot apply to:", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), GetStorageQualifierString(publicType.qualifier.storage));
8076     }
8077     if (publicType.shaderQualifiers.spacing != EvsNone) {
8078         if (publicType.qualifier.storage == EvqVaryingIn) {
8079             if (! intermediate.setVertexSpacing(publicType.shaderQualifiers.spacing))
8080                 error(loc, "cannot change previously set vertex spacing", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), "");
8081         } else
8082             error(loc, "can only apply to 'in'", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), "");
8083     }
8084     if (publicType.shaderQualifiers.order != EvoNone) {
8085         if (publicType.qualifier.storage == EvqVaryingIn) {
8086             if (! intermediate.setVertexOrder(publicType.shaderQualifiers.order))
8087                 error(loc, "cannot change previously set vertex order", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), "");
8088         } else
8089             error(loc, "can only apply to 'in'", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), "");
8090     }
8091     if (publicType.shaderQualifiers.pointMode) {
8092         if (publicType.qualifier.storage == EvqVaryingIn)
8093             intermediate.setPointMode();
8094         else
8095             error(loc, "can only apply to 'in'", "point_mode", "");
8096     }
8097 #endif
8098     for (int i = 0; i < 3; ++i) {
8099         if (publicType.shaderQualifiers.localSizeNotDefault[i]) {
8100             if (publicType.qualifier.storage == EvqVaryingIn) {
8101                 if (! intermediate.setLocalSize(i, publicType.shaderQualifiers.localSize[i]))
8102                     error(loc, "cannot change previously set size", "local_size", "");
8103                 else {
8104                     int max = 0;
8105                     if (language == EShLangCompute) {
8106                         switch (i) {
8107                         case 0: max = resources.maxComputeWorkGroupSizeX; break;
8108                         case 1: max = resources.maxComputeWorkGroupSizeY; break;
8109                         case 2: max = resources.maxComputeWorkGroupSizeZ; break;
8110                         default: break;
8111                         }
8112                         if (intermediate.getLocalSize(i) > (unsigned int)max)
8113                             error(loc, "too large; see gl_MaxComputeWorkGroupSize", "local_size", "");
8114                     }
8115 #ifndef GLSLANG_WEB
8116                     else if (language == EShLangMeshNV) {
8117                         switch (i) {
8118                         case 0: max = resources.maxMeshWorkGroupSizeX_NV; break;
8119                         case 1: max = resources.maxMeshWorkGroupSizeY_NV; break;
8120                         case 2: max = resources.maxMeshWorkGroupSizeZ_NV; break;
8121                         default: break;
8122                         }
8123                         if (intermediate.getLocalSize(i) > (unsigned int)max)
8124                             error(loc, "too large; see gl_MaxMeshWorkGroupSizeNV", "local_size", "");
8125                     } else if (language == EShLangTaskNV) {
8126                         switch (i) {
8127                         case 0: max = resources.maxTaskWorkGroupSizeX_NV; break;
8128                         case 1: max = resources.maxTaskWorkGroupSizeY_NV; break;
8129                         case 2: max = resources.maxTaskWorkGroupSizeZ_NV; break;
8130                         default: break;
8131                         }
8132                         if (intermediate.getLocalSize(i) > (unsigned int)max)
8133                             error(loc, "too large; see gl_MaxTaskWorkGroupSizeNV", "local_size", "");
8134                     }
8135 #endif
8136                     else {
8137                         assert(0);
8138                     }
8139 
8140                     // Fix the existing constant gl_WorkGroupSize with this new information.
8141                     TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize");
8142                     if (workGroupSize != nullptr)
8143                         workGroupSize->getWritableConstArray()[i].setUConst(intermediate.getLocalSize(i));
8144                 }
8145             } else
8146                 error(loc, "can only apply to 'in'", "local_size", "");
8147         }
8148         if (publicType.shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet) {
8149             if (publicType.qualifier.storage == EvqVaryingIn) {
8150                 if (! intermediate.setLocalSizeSpecId(i, publicType.shaderQualifiers.localSizeSpecId[i]))
8151                     error(loc, "cannot change previously set size", "local_size", "");
8152             } else
8153                 error(loc, "can only apply to 'in'", "local_size id", "");
8154             // Set the workgroup built-in variable as a specialization constant
8155             TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize");
8156             if (workGroupSize != nullptr)
8157                 workGroupSize->getWritableType().getQualifier().specConstant = true;
8158         }
8159     }
8160 
8161 #ifndef GLSLANG_WEB
8162     if (publicType.shaderQualifiers.earlyFragmentTests) {
8163         if (publicType.qualifier.storage == EvqVaryingIn)
8164             intermediate.setEarlyFragmentTests();
8165         else
8166             error(loc, "can only apply to 'in'", "early_fragment_tests", "");
8167     }
8168     if (publicType.shaderQualifiers.postDepthCoverage) {
8169         if (publicType.qualifier.storage == EvqVaryingIn)
8170             intermediate.setPostDepthCoverage();
8171         else
8172             error(loc, "can only apply to 'in'", "post_coverage_coverage", "");
8173     }
8174     if (publicType.shaderQualifiers.hasBlendEquation()) {
8175         if (publicType.qualifier.storage != EvqVaryingOut)
8176             error(loc, "can only apply to 'out'", "blend equation", "");
8177     }
8178     if (publicType.shaderQualifiers.interlockOrdering) {
8179         if (publicType.qualifier.storage == EvqVaryingIn) {
8180             if (!intermediate.setInterlockOrdering(publicType.shaderQualifiers.interlockOrdering))
8181                 error(loc, "cannot change previously set fragment shader interlock ordering", TQualifier::getInterlockOrderingString(publicType.shaderQualifiers.interlockOrdering), "");
8182         }
8183         else
8184             error(loc, "can only apply to 'in'", TQualifier::getInterlockOrderingString(publicType.shaderQualifiers.interlockOrdering), "");
8185     }
8186 
8187     if (publicType.shaderQualifiers.layoutDerivativeGroupQuads &&
8188         publicType.shaderQualifiers.layoutDerivativeGroupLinear) {
8189         error(loc, "cannot be both specified", "derivative_group_quadsNV and derivative_group_linearNV", "");
8190     }
8191 
8192     if (publicType.shaderQualifiers.layoutDerivativeGroupQuads) {
8193         if (publicType.qualifier.storage == EvqVaryingIn) {
8194             if ((intermediate.getLocalSize(0) & 1) ||
8195                 (intermediate.getLocalSize(1) & 1))
8196                 error(loc, "requires local_size_x and local_size_y to be multiple of two", "derivative_group_quadsNV", "");
8197             else
8198                 intermediate.setLayoutDerivativeMode(LayoutDerivativeGroupQuads);
8199         }
8200         else
8201             error(loc, "can only apply to 'in'", "derivative_group_quadsNV", "");
8202     }
8203     if (publicType.shaderQualifiers.layoutDerivativeGroupLinear) {
8204         if (publicType.qualifier.storage == EvqVaryingIn) {
8205             if((intermediate.getLocalSize(0) *
8206                 intermediate.getLocalSize(1) *
8207                 intermediate.getLocalSize(2)) % 4 != 0)
8208                 error(loc, "requires total group size to be multiple of four", "derivative_group_linearNV", "");
8209             else
8210                 intermediate.setLayoutDerivativeMode(LayoutDerivativeGroupLinear);
8211         }
8212         else
8213             error(loc, "can only apply to 'in'", "derivative_group_linearNV", "");
8214     }
8215     // Check mesh out array sizes, once all the necessary out qualifiers are defined.
8216     if ((language == EShLangMeshNV) &&
8217         (intermediate.getVertices() != TQualifier::layoutNotSet) &&
8218         (intermediate.getPrimitives() != TQualifier::layoutNotSet) &&
8219         (intermediate.getOutputPrimitive() != ElgNone))
8220     {
8221         checkIoArraysConsistency(loc);
8222     }
8223 #endif
8224     const TQualifier& qualifier = publicType.qualifier;
8225 
8226     if (qualifier.isAuxiliary() ||
8227         qualifier.isMemory() ||
8228         qualifier.isInterpolation() ||
8229         qualifier.precision != EpqNone)
8230         error(loc, "cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type)", "qualifier", "");
8231 
8232     // "The offset qualifier can only be used on block members of blocks..."
8233     // "The align qualifier can only be used on blocks or block members..."
8234     if (qualifier.hasOffset() ||
8235         qualifier.hasAlign())
8236         error(loc, "cannot use offset or align qualifiers in a default qualifier declaration (declaration with no type)", "layout qualifier", "");
8237 
8238     layoutQualifierCheck(loc, qualifier);
8239 
8240     switch (qualifier.storage) {
8241     case EvqUniform:
8242         if (qualifier.hasMatrix())
8243             globalUniformDefaults.layoutMatrix = qualifier.layoutMatrix;
8244         if (qualifier.hasPacking())
8245             globalUniformDefaults.layoutPacking = qualifier.layoutPacking;
8246         break;
8247     case EvqBuffer:
8248         if (qualifier.hasMatrix())
8249             globalBufferDefaults.layoutMatrix = qualifier.layoutMatrix;
8250         if (qualifier.hasPacking())
8251             globalBufferDefaults.layoutPacking = qualifier.layoutPacking;
8252         break;
8253     case EvqVaryingIn:
8254         break;
8255     case EvqVaryingOut:
8256 #ifndef GLSLANG_WEB
8257         if (qualifier.hasStream())
8258             globalOutputDefaults.layoutStream = qualifier.layoutStream;
8259         if (qualifier.hasXfbBuffer())
8260             globalOutputDefaults.layoutXfbBuffer = qualifier.layoutXfbBuffer;
8261         if (globalOutputDefaults.hasXfbBuffer() && qualifier.hasXfbStride()) {
8262             if (! intermediate.setXfbBufferStride(globalOutputDefaults.layoutXfbBuffer, qualifier.layoutXfbStride))
8263                 error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", qualifier.layoutXfbBuffer);
8264         }
8265 #endif
8266         break;
8267     default:
8268         error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", "");
8269         return;
8270     }
8271 
8272     if (qualifier.hasBinding())
8273         error(loc, "cannot declare a default, include a type or full declaration", "binding", "");
8274     if (qualifier.hasAnyLocation())
8275         error(loc, "cannot declare a default, use a full declaration", "location/component/index", "");
8276     if (qualifier.hasXfbOffset())
8277         error(loc, "cannot declare a default, use a full declaration", "xfb_offset", "");
8278     if (qualifier.isPushConstant())
8279         error(loc, "cannot declare a default, can only be used on a block", "push_constant", "");
8280     if (qualifier.hasBufferReference())
8281         error(loc, "cannot declare a default, can only be used on a block", "buffer_reference", "");
8282     if (qualifier.hasSpecConstantId())
8283         error(loc, "cannot declare a default, can only be used on a scalar", "constant_id", "");
8284     if (qualifier.isShaderRecord())
8285         error(loc, "cannot declare a default, can only be used on a block", "shaderRecordNV", "");
8286 }
8287 
8288 //
8289 // Take the sequence of statements that has been built up since the last case/default,
8290 // put it on the list of top-level nodes for the current (inner-most) switch statement,
8291 // and follow that by the case/default we are on now.  (See switch topology comment on
8292 // TIntermSwitch.)
8293 //
wrapupSwitchSubsequence(TIntermAggregate * statements,TIntermNode * branchNode)8294 void TParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode)
8295 {
8296     TIntermSequence* switchSequence = switchSequenceStack.back();
8297 
8298     if (statements) {
8299         if (switchSequence->size() == 0)
8300             error(statements->getLoc(), "cannot have statements before first case/default label", "switch", "");
8301         statements->setOperator(EOpSequence);
8302         switchSequence->push_back(statements);
8303     }
8304     if (branchNode) {
8305         // check all previous cases for the same label (or both are 'default')
8306         for (unsigned int s = 0; s < switchSequence->size(); ++s) {
8307             TIntermBranch* prevBranch = (*switchSequence)[s]->getAsBranchNode();
8308             if (prevBranch) {
8309                 TIntermTyped* prevExpression = prevBranch->getExpression();
8310                 TIntermTyped* newExpression = branchNode->getAsBranchNode()->getExpression();
8311                 if (prevExpression == nullptr && newExpression == nullptr)
8312                     error(branchNode->getLoc(), "duplicate label", "default", "");
8313                 else if (prevExpression != nullptr &&
8314                           newExpression != nullptr &&
8315                          prevExpression->getAsConstantUnion() &&
8316                           newExpression->getAsConstantUnion() &&
8317                          prevExpression->getAsConstantUnion()->getConstArray()[0].getIConst() ==
8318                           newExpression->getAsConstantUnion()->getConstArray()[0].getIConst())
8319                     error(branchNode->getLoc(), "duplicated value", "case", "");
8320             }
8321         }
8322         switchSequence->push_back(branchNode);
8323     }
8324 }
8325 
8326 //
8327 // Turn the top-level node sequence built up of wrapupSwitchSubsequence9)
8328 // into a switch node.
8329 //
addSwitch(const TSourceLoc & loc,TIntermTyped * expression,TIntermAggregate * lastStatements)8330 TIntermNode* TParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expression, TIntermAggregate* lastStatements)
8331 {
8332     profileRequires(loc, EEsProfile, 300, nullptr, "switch statements");
8333     profileRequires(loc, ENoProfile, 130, nullptr, "switch statements");
8334 
8335     wrapupSwitchSubsequence(lastStatements, nullptr);
8336 
8337     if (expression == nullptr ||
8338         (expression->getBasicType() != EbtInt && expression->getBasicType() != EbtUint) ||
8339         expression->getType().isArray() || expression->getType().isMatrix() || expression->getType().isVector())
8340             error(loc, "condition must be a scalar integer expression", "switch", "");
8341 
8342     // If there is nothing to do, drop the switch but still execute the expression
8343     TIntermSequence* switchSequence = switchSequenceStack.back();
8344     if (switchSequence->size() == 0)
8345         return expression;
8346 
8347     if (lastStatements == nullptr) {
8348         // This was originally an ERRROR, because early versions of the specification said
8349         // "it is an error to have no statement between a label and the end of the switch statement."
8350         // The specifications were updated to remove this (being ill-defined what a "statement" was),
8351         // so, this became a warning.  However, 3.0 tests still check for the error.
8352         if (isEsProfile() && version <= 300 && ! relaxedErrors())
8353             error(loc, "last case/default label not followed by statements", "switch", "");
8354         else
8355             warn(loc, "last case/default label not followed by statements", "switch", "");
8356 
8357         // emulate a break for error recovery
8358         lastStatements = intermediate.makeAggregate(intermediate.addBranch(EOpBreak, loc));
8359         lastStatements->setOperator(EOpSequence);
8360         switchSequence->push_back(lastStatements);
8361     }
8362 
8363     TIntermAggregate* body = new TIntermAggregate(EOpSequence);
8364     body->getSequence() = *switchSequenceStack.back();
8365     body->setLoc(loc);
8366 
8367     TIntermSwitch* switchNode = new TIntermSwitch(expression, body);
8368     switchNode->setLoc(loc);
8369 
8370     return switchNode;
8371 }
8372 
8373 } // end namespace glslang
8374 
8375