2 // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
3 // Copyright (C) 2016 Google, Inc.
5 // All rights reserved.
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
14 // Redistributions in binary form must reproduce the above
15 // copyright notice, this list of conditions and the following
16 // disclaimer in the documentation and/or other materials provided
17 // with the distribution.
19 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
20 // contributors may be used to endorse or promote products derived
21 // from this software without specific prior written permission.
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 // POSSIBILITY OF SUCH DAMAGE.
37 // Implement the TParseContextBase class.
41 #include "ParseHelper.h"
43 extern int yyparse(glslang::TParseContext*);
48 // Used to output syntax, parsing, and semantic errors.
51 void TParseContextBase::outputMessage(const TSourceLoc& loc, const char* szReason,
53 const char* szExtraInfoFormat,
54 TPrefixType prefix, va_list args)
56 const int maxSize = MaxTokenLength + 200;
57 char szExtraInfo[maxSize];
59 safe_vsprintf(szExtraInfo, maxSize, szExtraInfoFormat, args);
61 infoSink.info.prefix(prefix);
62 infoSink.info.location(loc);
63 infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n";
65 if (prefix == EPrefixError) {
70 #if !defined(GLSLANG_WEB) || defined(GLSLANG_WEB_DEVEL)
72 void C_DECL TParseContextBase::error(const TSourceLoc& loc, const char* szReason, const char* szToken,
73 const char* szExtraInfoFormat, ...)
75 if (messages & EShMsgOnlyPreprocessor)
78 va_start(args, szExtraInfoFormat);
79 outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
82 if ((messages & EShMsgCascadingErrors) == 0)
83 currentScanner->setEndOfInput();
86 void C_DECL TParseContextBase::warn(const TSourceLoc& loc, const char* szReason, const char* szToken,
87 const char* szExtraInfoFormat, ...)
89 if (suppressWarnings())
92 va_start(args, szExtraInfoFormat);
93 outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args);
97 void C_DECL TParseContextBase::ppError(const TSourceLoc& loc, const char* szReason, const char* szToken,
98 const char* szExtraInfoFormat, ...)
101 va_start(args, szExtraInfoFormat);
102 outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
105 if ((messages & EShMsgCascadingErrors) == 0)
106 currentScanner->setEndOfInput();
109 void C_DECL TParseContextBase::ppWarn(const TSourceLoc& loc, const char* szReason, const char* szToken,
110 const char* szExtraInfoFormat, ...)
113 va_start(args, szExtraInfoFormat);
114 outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args);
121 // Both test and if necessary, spit out an error, to see if the node is really
122 // an l-value that can be operated on this way.
124 // Returns true if there was an error.
126 bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
128 TIntermBinary* binaryNode = node->getAsBinaryNode();
130 const char* symbol = nullptr;
131 TIntermSymbol* symNode = node->getAsSymbolNode();
132 if (symNode != nullptr)
133 symbol = symNode->getName().c_str();
135 const char* message = nullptr;
136 switch (node->getQualifier().storage) {
137 case EvqConst: message = "can't modify a const"; break;
138 case EvqConstReadOnly: message = "can't modify a const"; break;
139 case EvqUniform: message = "can't modify a uniform"; break;
142 if (node->getQualifier().isReadOnly())
143 message = "can't modify a readonly buffer";
144 if (node->getQualifier().isShaderRecord())
145 message = "can't modify a shaderrecordnv qualified buffer";
148 if (language != EShLangIntersect)
149 message = "cannot modify hitAttributeNV in this stage";
155 // Type that can't be written to?
157 switch (node->getBasicType()) {
159 message = "can't modify a sampler";
162 message = "can't modify void";
166 message = "can't modify an atomic_uint";
169 message = "can't modify accelerationStructureNV";
172 message = "can't modify rayQueryEXT";
180 if (message == nullptr && binaryNode == nullptr && symNode == nullptr) {
181 error(loc, " l-value required", op, "", "");
187 // Everything else is okay, no error.
189 if (message == nullptr)
192 switch (binaryNode->getOp()) {
194 case EOpIndexIndirect: // fall through
195 case EOpIndexDirectStruct: // fall through
196 case EOpVectorSwizzle:
197 case EOpMatrixSwizzle:
198 return lValueErrorCheck(loc, op, binaryNode->getLeft());
202 error(loc, " l-value required", op, "", "");
210 // If we get here, we have an error and a message.
212 const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true);
215 error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
217 if (binaryNode && binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct)
218 if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName()))
219 error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str(), message);
221 error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getName().c_str(), message);
223 error(loc, " l-value required", op, "(%s)", message);
228 // Test for and give an error if the node can't be read from.
229 void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
231 TIntermBinary* binaryNode = node->getAsBinaryNode();
232 const TIntermSymbol* symNode = node->getAsSymbolNode();
237 if (node->getQualifier().isWriteOnly()) {
238 const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true);
240 if (symNode != nullptr)
241 error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
242 else if (binaryNode &&
243 (binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct ||
244 binaryNode->getAsOperator()->getOp() == EOpIndexDirect))
245 if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName()))
246 error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str());
248 error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getName().c_str());
250 error(loc, "can't read from writeonly object: ", op, "");
254 switch (binaryNode->getOp()) {
256 case EOpIndexIndirect:
257 case EOpIndexDirectStruct:
258 case EOpVectorSwizzle:
259 case EOpMatrixSwizzle:
260 rValueErrorCheck(loc, op, binaryNode->getLeft());
268 // Add 'symbol' to the list of deferred linkage symbols, which
269 // are later processed in finish(), at which point the symbol
270 // must still be valid.
271 // It is okay if the symbol's type will be subsequently edited;
272 // the modifications will be tracked.
273 // Order is preserved, to avoid creating novel forward references.
274 void TParseContextBase::trackLinkage(TSymbol& symbol)
276 if (!parsingBuiltins)
277 linkageSymbols.push_back(&symbol);
280 // Ensure index is in bounds, correct if necessary.
281 // Give an error if not.
282 void TParseContextBase::checkIndex(const TSourceLoc& loc, const TType& type, int& index)
284 const auto sizeIsSpecializationExpression = [&type]() {
285 return type.containsSpecializationSize() &&
286 type.getArraySizes()->getOuterNode() != nullptr &&
287 type.getArraySizes()->getOuterNode()->getAsSymbolNode() == nullptr; };
290 error(loc, "", "[", "index out of range '%d'", index);
292 } else if (type.isArray()) {
293 if (type.isSizedArray() && !sizeIsSpecializationExpression() &&
294 index >= type.getOuterArraySize()) {
295 error(loc, "", "[", "array index out of range '%d'", index);
296 index = type.getOuterArraySize() - 1;
298 } else if (type.isVector()) {
299 if (index >= type.getVectorSize()) {
300 error(loc, "", "[", "vector index out of range '%d'", index);
301 index = type.getVectorSize() - 1;
303 } else if (type.isMatrix()) {
304 if (index >= type.getMatrixCols()) {
305 error(loc, "", "[", "matrix index out of range '%d'", index);
306 index = type.getMatrixCols() - 1;
311 // Make a shared symbol have a non-shared version that can be edited by the current
312 // compile, such that editing its type will not change the shared version and will
313 // effect all nodes already sharing it (non-shallow type),
314 // or adopting its full type after being edited (shallow type).
315 void TParseContextBase::makeEditable(TSymbol*& symbol)
317 // copyUp() does a deep copy of the type.
318 symbol = symbolTable.copyUp(symbol);
320 // Save it (deferred, so it can be edited first) in the AST for linker use.
322 trackLinkage(*symbol);
325 // Return a writable version of the variable 'name'.
327 // Return nullptr if 'name' is not found. This should mean
328 // something is seriously wrong (e.g., compiler asking self for
329 // built-in that doesn't exist).
330 TVariable* TParseContextBase::getEditableVariable(const char* name)
333 TSymbol* symbol = symbolTable.find(name, &builtIn);
335 assert(symbol != nullptr);
336 if (symbol == nullptr)
340 makeEditable(symbol);
342 return symbol->getAsVariable();
345 // Select the best matching function for 'call' from 'candidateList'.
349 // There is no exact match, so a selection algorithm needs to run. That is, the
350 // language-specific handler should check for exact match first, to
351 // decide what to do, before calling this selector.
355 // * list of candidate signatures to select from
357 // * a predicate function convertible(from, to) that says whether or not type
358 // 'from' can implicitly convert to type 'to' (it includes the case of what
359 // the calling language would consider a matching type with no conversion
361 // * a predicate function better(from1, from2, to1, to2) that says whether or
362 // not a conversion from <-> to2 is considered better than a conversion
363 // from <-> to1 (both in and out directions need testing, as declared by the
368 // * best matching candidate (or none, if no viable candidates found)
369 // * whether there was a tie for the best match (ambiguous overload selection,
370 // caller's choice for how to report)
372 const TFunction* TParseContextBase::selectFunction(
373 const TVector<const TFunction*> candidateList,
374 const TFunction& call,
375 std::function<bool(const TType& from, const TType& to, TOperator op, int arg)> convertible,
376 std::function<bool(const TType& from, const TType& to1, const TType& to2)> better,
377 /* output */ bool& tie)
382 // 1. Prune the input list of candidates down to a list of viable candidates,
383 // where each viable candidate has
385 // * at least as many parameters as there are calling arguments, with any
386 // remaining parameters being optional or having default values
387 // * each parameter is true under convertible(A, B), where A is the calling
388 // type for in and B is the formal type, and in addition, for out B is the
389 // calling type and A is the formal type
391 // 2. If there are no viable candidates, return with no match.
393 // 3. If there is only one viable candidate, it is the best match.
395 // 4. If there are multiple viable candidates, select the first viable candidate
396 // as the incumbent. Compare the incumbent to the next viable candidate, and if
397 // that candidate is better (bullets below), make it the incumbent. Repeat, with
398 // a linear walk through the viable candidate list. The final incumbent will be
399 // returned as the best match. A viable candidate is better than the incumbent if
401 // * it has a function argument with a better(...) conversion than the incumbent,
402 // for all directions needed by in and out
403 // * the incumbent has no argument with a better(...) conversion then the
404 // candidate, for either in or out (as needed)
406 // 5. Check for ambiguity by comparing the best match against all other viable
407 // candidates. If any other viable candidate has a function argument with a
408 // better(...) conversion than the best candidate (for either in or out
409 // directions), return that there was a tie for best.
414 // 1. prune to viable...
415 TVector<const TFunction*> viableCandidates;
416 for (auto it = candidateList.begin(); it != candidateList.end(); ++it) {
417 const TFunction& candidate = *(*it);
419 // to even be a potential match, number of arguments must be >= the number of
420 // fixed (non-default) parameters, and <= the total (including parameter with defaults).
421 if (call.getParamCount() < candidate.getFixedParamCount() ||
422 call.getParamCount() > candidate.getParamCount())
425 // see if arguments are convertible
428 // The call can have fewer parameters than the candidate, if some have defaults.
429 const int paramCount = std::min(call.getParamCount(), candidate.getParamCount());
430 for (int param = 0; param < paramCount; ++param) {
431 if (candidate[param].type->getQualifier().isParamInput()) {
432 if (! convertible(*call[param].type, *candidate[param].type, candidate.getBuiltInOp(), param)) {
437 if (candidate[param].type->getQualifier().isParamOutput()) {
438 if (! convertible(*candidate[param].type, *call[param].type, candidate.getBuiltInOp(), param)) {
446 viableCandidates.push_back(&candidate);
450 if (viableCandidates.size() == 0)
453 // 3. only one viable...
454 if (viableCandidates.size() == 1)
455 return viableCandidates.front();
458 const auto betterParam = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool {
459 // is call -> can2 better than call -> can1 for any parameter
460 bool hasBetterParam = false;
461 for (int param = 0; param < call.getParamCount(); ++param) {
462 if (better(*call[param].type, *can1[param].type, *can2[param].type)) {
463 hasBetterParam = true;
467 return hasBetterParam;
470 const auto equivalentParams = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool {
471 // is call -> can2 equivalent to call -> can1 for all the call parameters?
472 for (int param = 0; param < call.getParamCount(); ++param) {
473 if (better(*call[param].type, *can1[param].type, *can2[param].type) ||
474 better(*call[param].type, *can2[param].type, *can1[param].type))
480 const TFunction* incumbent = viableCandidates.front();
481 for (auto it = viableCandidates.begin() + 1; it != viableCandidates.end(); ++it) {
482 const TFunction& candidate = *(*it);
483 if (betterParam(*incumbent, candidate) && ! betterParam(candidate, *incumbent))
484 incumbent = &candidate;
488 for (auto it = viableCandidates.begin(); it != viableCandidates.end(); ++it) {
489 if (incumbent == *it)
491 const TFunction& candidate = *(*it);
493 // In the case of default parameters, it may have an identical initial set, which is
495 if (betterParam(*incumbent, candidate) || equivalentParams(*incumbent, candidate))
503 // Look at a '.' field selector string and change it into numerical selectors
504 // for a vector or scalar.
506 // Always return some form of swizzle, so the result is always usable.
508 void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TString& compString, int vecSize,
509 TSwizzleSelectors<TVectorSelector>& selector)
512 if (compString.size() > MaxSwizzleSelectors)
513 error(loc, "vector swizzle too long", compString.c_str(), "");
515 // Use this to test that all swizzle characters are from the same swizzle-namespace-set
520 } fieldSet[MaxSwizzleSelectors];
522 // Decode the swizzle string.
523 int size = std::min(MaxSwizzleSelectors, (int)compString.size());
524 for (int i = 0; i < size; ++i) {
525 switch (compString[i]) {
527 selector.push_back(0);
531 selector.push_back(0);
535 selector.push_back(0);
540 selector.push_back(1);
544 selector.push_back(1);
548 selector.push_back(1);
553 selector.push_back(2);
557 selector.push_back(2);
561 selector.push_back(2);
566 selector.push_back(3);
570 selector.push_back(3);
574 selector.push_back(3);
579 error(loc, "unknown swizzle selection", compString.c_str(), "");
584 // Additional error checking.
585 for (int i = 0; i < selector.size(); ++i) {
586 if (selector[i] >= vecSize) {
587 error(loc, "vector swizzle selection out of range", compString.c_str(), "");
592 if (i > 0 && fieldSet[i] != fieldSet[i-1]) {
593 error(loc, "vector swizzle selectors not from the same set", compString.c_str(), "");
599 // Ensure it is valid.
600 if (selector.size() == 0)
601 selector.push_back(0);
605 // Make the passed-in variable information become a member of the
606 // global uniform block. If this doesn't exist yet, make it.
608 void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList)
610 // Make the global block, if not yet made.
611 if (globalUniformBlock == nullptr) {
612 TQualifier blockQualifier;
613 blockQualifier.clear();
614 blockQualifier.storage = EvqUniform;
615 TType blockType(new TTypeList, *NewPoolTString(getGlobalUniformBlockName()), blockQualifier);
616 setUniformBlockDefaults(blockType);
617 globalUniformBlock = new TVariable(NewPoolTString(""), blockType, true);
621 // Update with binding and set
622 globalUniformBlock->getWritableType().getQualifier().layoutBinding = globalUniformBinding;
623 globalUniformBlock->getWritableType().getQualifier().layoutSet = globalUniformSet;
625 // Check for declarations of this default uniform that already exist due to other compilation units.
626 TSymbol* symbol = symbolTable.find(memberName);
628 if (memberType != symbol->getType()) {
630 err += "\"" + memberType.getCompleteString() + "\"";
632 err += "\"" + symbol->getType().getCompleteString() + "\"";
633 error(loc, "Types must match:", memberType.getFieldName().c_str(), err.c_str());
638 // Add the requested member as a member to the global block.
639 TType* type = new TType;
640 type->shallowCopy(memberType);
641 type->setFieldName(memberName);
643 type->setStruct(typeList);
644 TTypeLoc typeLoc = {type, loc};
645 globalUniformBlock->getType().getWritableStruct()->push_back(typeLoc);
647 // Insert into the symbol table.
648 if (firstNewMember == 0) {
649 // This is the first request; we need a normal symbol table insert
650 if (symbolTable.insert(*globalUniformBlock))
651 trackLinkage(*globalUniformBlock);
653 error(loc, "failed to insert the global constant buffer", "uniform", "");
655 // This is a follow-on request; we need to amend the first insert
656 symbolTable.amend(*globalUniformBlock, firstNewMember);
662 void TParseContextBase::growAtomicCounterBlock(int binding, const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) {
663 // Make the atomic counter block, if not yet made.
664 const auto &at = atomicCounterBuffers.find(binding);
665 if (at == atomicCounterBuffers.end()) {
666 atomicCounterBuffers.insert({binding, (TVariable*)nullptr });
667 atomicCounterBlockFirstNewMember.insert({binding, 0});
670 TVariable*& atomicCounterBuffer = atomicCounterBuffers[binding];
671 int& bufferNewMember = atomicCounterBlockFirstNewMember[binding];
673 if (atomicCounterBuffer == nullptr) {
674 TQualifier blockQualifier;
675 blockQualifier.clear();
676 blockQualifier.storage = EvqBuffer;
678 char charBuffer[512];
679 if (binding != TQualifier::layoutBindingEnd) {
680 snprintf(charBuffer, 512, "%s_%d", getAtomicCounterBlockName(), binding);
682 snprintf(charBuffer, 512, "%s_0", getAtomicCounterBlockName());
685 TType blockType(new TTypeList, *NewPoolTString(charBuffer), blockQualifier);
686 setUniformBlockDefaults(blockType);
687 blockType.getQualifier().layoutPacking = ElpStd430;
688 atomicCounterBuffer = new TVariable(NewPoolTString(""), blockType, true);
689 // If we arn't auto mapping bindings then set the block to use the same
690 // binding as what the atomic was set to use
691 if (!intermediate.getAutoMapBindings()) {
692 atomicCounterBuffer->getWritableType().getQualifier().layoutBinding = binding;
696 atomicCounterBuffer->getWritableType().getQualifier().layoutSet = atomicCounterBlockSet;
699 // Add the requested member as a member to the global block.
700 TType* type = new TType;
701 type->shallowCopy(memberType);
702 type->setFieldName(memberName);
704 type->setStruct(typeList);
705 TTypeLoc typeLoc = {type, loc};
706 atomicCounterBuffer->getType().getWritableStruct()->push_back(typeLoc);
708 // Insert into the symbol table.
709 if (bufferNewMember == 0) {
710 // This is the first request; we need a normal symbol table insert
711 if (symbolTable.insert(*atomicCounterBuffer))
712 trackLinkage(*atomicCounterBuffer);
714 error(loc, "failed to insert the global constant buffer", "buffer", "");
716 // This is a follow-on request; we need to amend the first insert
717 symbolTable.amend(*atomicCounterBuffer, bufferNewMember);
723 void TParseContextBase::finish()
728 // Transfer the linkage symbols to AST nodes, preserving order.
729 TIntermAggregate* linkage = new TIntermAggregate;
730 for (auto i = linkageSymbols.begin(); i != linkageSymbols.end(); ++i)
731 intermediate.addSymbolLinkageNode(linkage, **i);
732 intermediate.addSymbolLinkageNodes(linkage, getLanguage(), symbolTable);
735 } // end namespace glslang