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