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, ¤tScope);
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