1//
2// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
3// Copyright (C) 2016 Google, Inc.
4//
5// All rights reserved.
6//
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions
9// are met:
10//
11// Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13//
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.
18//
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.
22//
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.
35//
36
37// Implement the TParseContextBase class.
38
39#include <cstdarg>
40
41#include "ParseHelper.h"
42
43extern int yyparse(glslang::TParseContext*);
44
45namespace glslang {
46
47//
48// Used to output syntax, parsing, and semantic errors.
49//
50
51void TParseContextBase::outputMessage(const TSourceLoc& loc, const char* szReason,
52 const char* szToken,
53 const char* szExtraInfoFormat,
54 TPrefixType prefix, va_list args)
55{
56 const int maxSize = MaxTokenLength + 200;
57 char szExtraInfo[maxSize];
58
59 safe_vsprintf(szExtraInfo, maxSize, szExtraInfoFormat, args);
60
61 infoSink.info.prefix(prefix);
62 infoSink.info.location(loc);
63 infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n";
64
65 if (prefix == EPrefixError) {
66 ++numErrors;
67 }
68}
69
70void C_DECL TParseContextBase::error(const TSourceLoc& loc, const char* szReason, const char* szToken,
71 const char* szExtraInfoFormat, ...)
72{
73 if (messages & EShMsgOnlyPreprocessor)
74 return;
75 va_list args;
76 va_start(args, szExtraInfoFormat);
77 outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
78 va_end(args);
79
80 if ((messages & EShMsgCascadingErrors) == 0)
81 currentScanner->setEndOfInput();
82}
83
84void C_DECL TParseContextBase::warn(const TSourceLoc& loc, const char* szReason, const char* szToken,
85 const char* szExtraInfoFormat, ...)
86{
87 if (suppressWarnings())
88 return;
89 va_list args;
90 va_start(args, szExtraInfoFormat);
91 outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args);
92 va_end(args);
93}
94
95void C_DECL TParseContextBase::ppError(const TSourceLoc& loc, const char* szReason, const char* szToken,
96 const char* szExtraInfoFormat, ...)
97{
98 va_list args;
99 va_start(args, szExtraInfoFormat);
100 outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
101 va_end(args);
102
103 if ((messages & EShMsgCascadingErrors) == 0)
104 currentScanner->setEndOfInput();
105}
106
107void C_DECL TParseContextBase::ppWarn(const TSourceLoc& loc, const char* szReason, const char* szToken,
108 const char* szExtraInfoFormat, ...)
109{
110 va_list args;
111 va_start(args, szExtraInfoFormat);
112 outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args);
113 va_end(args);
114}
115
116//
117// Both test and if necessary, spit out an error, to see if the node is really
118// an l-value that can be operated on this way.
119//
120// Returns true if there was an error.
121//
122bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
123{
124 TIntermBinary* binaryNode = node->getAsBinaryNode();
125
126 if (binaryNode) {
127 switch(binaryNode->getOp()) {
128 case EOpIndexDirect:
129 case EOpIndexIndirect: // fall through
130 case EOpIndexDirectStruct: // fall through
131 case EOpVectorSwizzle:
132 case EOpMatrixSwizzle:
133 return lValueErrorCheck(loc, op, binaryNode->getLeft());
134 default:
135 break;
136 }
137 error(loc, " l-value required", op, "", "");
138
139 return true;
140 }
141
142 const char* symbol = nullptr;
143 TIntermSymbol* symNode = node->getAsSymbolNode();
144 if (symNode != nullptr)
145 symbol = symNode->getName().c_str();
146
147 const char* message = nullptr;
148 switch (node->getQualifier().storage) {
149 case EvqConst: message = "can't modify a const"; break;
150 case EvqConstReadOnly: message = "can't modify a const"; break;
151 case EvqUniform: message = "can't modify a uniform"; break;
152 case EvqBuffer:
153 if (node->getQualifier().readonly)
154 message = "can't modify a readonly buffer";
155#ifdef NV_EXTENSIONS
156 if (node->getQualifier().layoutShaderRecordNV)
157 message = "can't modify a shaderrecordnv qualified buffer";
158#endif
159 break;
160#ifdef NV_EXTENSIONS
161 case EvqHitAttrNV:
162 if (language != EShLangIntersectNV)
163 message = "cannot modify hitAttributeNV in this stage";
164 break;
165#endif
166
167 default:
168 //
169 // Type that can't be written to?
170 //
171 switch (node->getBasicType()) {
172 case EbtSampler:
173 message = "can't modify a sampler";
174 break;
175 case EbtAtomicUint:
176 message = "can't modify an atomic_uint";
177 break;
178 case EbtVoid:
179 message = "can't modify void";
180 break;
181#ifdef NV_EXTENSIONS
182 case EbtAccStructNV:
183 message = "can't modify accelerationStructureNV";
184 break;
185#endif
186 default:
187 break;
188 }
189 }
190
191 if (message == nullptr && binaryNode == nullptr && symNode == nullptr) {
192 error(loc, " l-value required", op, "", "");
193
194 return true;
195 }
196
197 //
198 // Everything else is okay, no error.
199 //
200 if (message == nullptr)
201 return false;
202
203 //
204 // If we get here, we have an error and a message.
205 //
206 if (symNode)
207 error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
208 else
209 error(loc, " l-value required", op, "(%s)", message);
210
211 return true;
212}
213
214// Test for and give an error if the node can't be read from.
215void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
216{
217 if (! node)
218 return;
219
220 TIntermBinary* binaryNode = node->getAsBinaryNode();
221 if (binaryNode) {
222 switch(binaryNode->getOp()) {
223 case EOpIndexDirect:
224 case EOpIndexIndirect:
225 case EOpIndexDirectStruct:
226 case EOpVectorSwizzle:
227 case EOpMatrixSwizzle:
228 rValueErrorCheck(loc, op, binaryNode->getLeft());
229 default:
230 break;
231 }
232
233 return;
234 }
235
236 TIntermSymbol* symNode = node->getAsSymbolNode();
237 if (symNode && symNode->getQualifier().writeonly)
238 error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
239}
240
241// Add 'symbol' to the list of deferred linkage symbols, which
242// are later processed in finish(), at which point the symbol
243// must still be valid.
244// It is okay if the symbol's type will be subsequently edited;
245// the modifications will be tracked.
246// Order is preserved, to avoid creating novel forward references.
247void TParseContextBase::trackLinkage(TSymbol& symbol)
248{
249 if (!parsingBuiltins)
250 linkageSymbols.push_back(&symbol);
251}
252
253// Ensure index is in bounds, correct if necessary.
254// Give an error if not.
255void TParseContextBase::checkIndex(const TSourceLoc& loc, const TType& type, int& index)
256{
257 if (index < 0) {
258 error(loc, "", "[", "index out of range '%d'", index);
259 index = 0;
260 } else if (type.isArray()) {
261 if (type.isSizedArray() && index >= type.getOuterArraySize()) {
262 error(loc, "", "[", "array index out of range '%d'", index);
263 index = type.getOuterArraySize() - 1;
264 }
265 } else if (type.isVector()) {
266 if (index >= type.getVectorSize()) {
267 error(loc, "", "[", "vector index out of range '%d'", index);
268 index = type.getVectorSize() - 1;
269 }
270 } else if (type.isMatrix()) {
271 if (index >= type.getMatrixCols()) {
272 error(loc, "", "[", "matrix index out of range '%d'", index);
273 index = type.getMatrixCols() - 1;
274 }
275 }
276}
277
278// Make a shared symbol have a non-shared version that can be edited by the current
279// compile, such that editing its type will not change the shared version and will
280// effect all nodes already sharing it (non-shallow type),
281// or adopting its full type after being edited (shallow type).
282void TParseContextBase::makeEditable(TSymbol*& symbol)
283{
284 // copyUp() does a deep copy of the type.
285 symbol = symbolTable.copyUp(symbol);
286
287 // Save it (deferred, so it can be edited first) in the AST for linker use.
288 if (symbol)
289 trackLinkage(*symbol);
290}
291
292// Return a writable version of the variable 'name'.
293//
294// Return nullptr if 'name' is not found. This should mean
295// something is seriously wrong (e.g., compiler asking self for
296// built-in that doesn't exist).
297TVariable* TParseContextBase::getEditableVariable(const char* name)
298{
299 bool builtIn;
300 TSymbol* symbol = symbolTable.find(name, &builtIn);
301
302 assert(symbol != nullptr);
303 if (symbol == nullptr)
304 return nullptr;
305
306 if (builtIn)
307 makeEditable(symbol);
308
309 return symbol->getAsVariable();
310}
311
312// Select the best matching function for 'call' from 'candidateList'.
313//
314// Assumptions
315//
316// There is no exact match, so a selection algorithm needs to run. That is, the
317// language-specific handler should check for exact match first, to
318// decide what to do, before calling this selector.
319//
320// Input
321//
322// * list of candidate signatures to select from
323// * the call
324// * a predicate function convertible(from, to) that says whether or not type
325// 'from' can implicitly convert to type 'to' (it includes the case of what
326// the calling language would consider a matching type with no conversion
327// needed)
328// * a predicate function better(from1, from2, to1, to2) that says whether or
329// not a conversion from <-> to2 is considered better than a conversion
330// from <-> to1 (both in and out directions need testing, as declared by the
331// formal parameter)
332//
333// Output
334//
335// * best matching candidate (or none, if no viable candidates found)
336// * whether there was a tie for the best match (ambiguous overload selection,
337// caller's choice for how to report)
338//
339const TFunction* TParseContextBase::selectFunction(
340 const TVector<const TFunction*> candidateList,
341 const TFunction& call,
342 std::function<bool(const TType& from, const TType& to, TOperator op, int arg)> convertible,
343 std::function<bool(const TType& from, const TType& to1, const TType& to2)> better,
344 /* output */ bool& tie)
345{
346//
347// Operation
348//
349// 1. Prune the input list of candidates down to a list of viable candidates,
350// where each viable candidate has
351//
352// * at least as many parameters as there are calling arguments, with any
353// remaining parameters being optional or having default values
354// * each parameter is true under convertible(A, B), where A is the calling
355// type for in and B is the formal type, and in addition, for out B is the
356// calling type and A is the formal type
357//
358// 2. If there are no viable candidates, return with no match.
359//
360// 3. If there is only one viable candidate, it is the best match.
361//
362// 4. If there are multiple viable candidates, select the first viable candidate
363// as the incumbent. Compare the incumbent to the next viable candidate, and if
364// that candidate is better (bullets below), make it the incumbent. Repeat, with
365// a linear walk through the viable candidate list. The final incumbent will be
366// returned as the best match. A viable candidate is better than the incumbent if
367//
368// * it has a function argument with a better(...) conversion than the incumbent,
369// for all directions needed by in and out
370// * the incumbent has no argument with a better(...) conversion then the
371// candidate, for either in or out (as needed)
372//
373// 5. Check for ambiguity by comparing the best match against all other viable
374// candidates. If any other viable candidate has a function argument with a
375// better(...) conversion than the best candidate (for either in or out
376// directions), return that there was a tie for best.
377//
378
379 tie = false;
380
381 // 1. prune to viable...
382 TVector<const TFunction*> viableCandidates;
383 for (auto it = candidateList.begin(); it != candidateList.end(); ++it) {
384 const TFunction& candidate = *(*it);
385
386 // to even be a potential match, number of arguments must be >= the number of
387 // fixed (non-default) parameters, and <= the total (including parameter with defaults).
388 if (call.getParamCount() < candidate.getFixedParamCount() ||
389 call.getParamCount() > candidate.getParamCount())
390 continue;
391
392 // see if arguments are convertible
393 bool viable = true;
394
395 // The call can have fewer parameters than the candidate, if some have defaults.
396 const int paramCount = std::min(call.getParamCount(), candidate.getParamCount());
397 for (int param = 0; param < paramCount; ++param) {
398 if (candidate[param].type->getQualifier().isParamInput()) {
399 if (! convertible(*call[param].type, *candidate[param].type, candidate.getBuiltInOp(), param)) {
400 viable = false;
401 break;
402 }
403 }
404 if (candidate[param].type->getQualifier().isParamOutput()) {
405 if (! convertible(*candidate[param].type, *call[param].type, candidate.getBuiltInOp(), param)) {
406 viable = false;
407 break;
408 }
409 }
410 }
411
412 if (viable)
413 viableCandidates.push_back(&candidate);
414 }
415
416 // 2. none viable...
417 if (viableCandidates.size() == 0)
418 return nullptr;
419
420 // 3. only one viable...
421 if (viableCandidates.size() == 1)
422 return viableCandidates.front();
423
424 // 4. find best...
425 const auto betterParam = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool {
426 // is call -> can2 better than call -> can1 for any parameter
427 bool hasBetterParam = false;
428 for (int param = 0; param < call.getParamCount(); ++param) {
429 if (better(*call[param].type, *can1[param].type, *can2[param].type)) {
430 hasBetterParam = true;
431 break;
432 }
433 }
434 return hasBetterParam;
435 };
436
437 const auto equivalentParams = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool {
438 // is call -> can2 equivalent to call -> can1 for all the call parameters?
439 for (int param = 0; param < call.getParamCount(); ++param) {
440 if (better(*call[param].type, *can1[param].type, *can2[param].type) ||
441 better(*call[param].type, *can2[param].type, *can1[param].type))
442 return false;
443 }
444 return true;
445 };
446
447 const TFunction* incumbent = viableCandidates.front();
448 for (auto it = viableCandidates.begin() + 1; it != viableCandidates.end(); ++it) {
449 const TFunction& candidate = *(*it);
450 if (betterParam(*incumbent, candidate) && ! betterParam(candidate, *incumbent))
451 incumbent = &candidate;
452 }
453
454 // 5. ambiguity...
455 for (auto it = viableCandidates.begin(); it != viableCandidates.end(); ++it) {
456 if (incumbent == *it)
457 continue;
458 const TFunction& candidate = *(*it);
459
460 // In the case of default parameters, it may have an identical initial set, which is
461 // also ambiguous
462 if (betterParam(*incumbent, candidate) || equivalentParams(*incumbent, candidate))
463 tie = true;
464 }
465
466 return incumbent;
467}
468
469//
470// Look at a '.' field selector string and change it into numerical selectors
471// for a vector or scalar.
472//
473// Always return some form of swizzle, so the result is always usable.
474//
475void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TString& compString, int vecSize,
476 TSwizzleSelectors<TVectorSelector>& selector)
477{
478 // Too long?
479 if (compString.size() > MaxSwizzleSelectors)
480 error(loc, "vector swizzle too long", compString.c_str(), "");
481
482 // Use this to test that all swizzle characters are from the same swizzle-namespace-set
483 enum {
484 exyzw,
485 ergba,
486 estpq,
487 } fieldSet[MaxSwizzleSelectors];
488
489 // Decode the swizzle string.
490 int size = std::min(MaxSwizzleSelectors, (int)compString.size());
491 for (int i = 0; i < size; ++i) {
492 switch (compString[i]) {
493 case 'x':
494 selector.push_back(0);
495 fieldSet[i] = exyzw;
496 break;
497 case 'r':
498 selector.push_back(0);
499 fieldSet[i] = ergba;
500 break;
501 case 's':
502 selector.push_back(0);
503 fieldSet[i] = estpq;
504 break;
505
506 case 'y':
507 selector.push_back(1);
508 fieldSet[i] = exyzw;
509 break;
510 case 'g':
511 selector.push_back(1);
512 fieldSet[i] = ergba;
513 break;
514 case 't':
515 selector.push_back(1);
516 fieldSet[i] = estpq;
517 break;
518
519 case 'z':
520 selector.push_back(2);
521 fieldSet[i] = exyzw;
522 break;
523 case 'b':
524 selector.push_back(2);
525 fieldSet[i] = ergba;
526 break;
527 case 'p':
528 selector.push_back(2);
529 fieldSet[i] = estpq;
530 break;
531
532 case 'w':
533 selector.push_back(3);
534 fieldSet[i] = exyzw;
535 break;
536 case 'a':
537 selector.push_back(3);
538 fieldSet[i] = ergba;
539 break;
540 case 'q':
541 selector.push_back(3);
542 fieldSet[i] = estpq;
543 break;
544
545 default:
546 error(loc, "unknown swizzle selection", compString.c_str(), "");
547 break;
548 }
549 }
550
551 // Additional error checking.
552 for (int i = 0; i < selector.size(); ++i) {
553 if (selector[i] >= vecSize) {
554 error(loc, "vector swizzle selection out of range", compString.c_str(), "");
555 selector.resize(i);
556 break;
557 }
558
559 if (i > 0 && fieldSet[i] != fieldSet[i-1]) {
560 error(loc, "vector swizzle selectors not from the same set", compString.c_str(), "");
561 selector.resize(i);
562 break;
563 }
564 }
565
566 // Ensure it is valid.
567 if (selector.size() == 0)
568 selector.push_back(0);
569}
570
571//
572// Make the passed-in variable information become a member of the
573// global uniform block. If this doesn't exist yet, make it.
574//
575void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList)
576{
577 // Make the global block, if not yet made.
578 if (globalUniformBlock == nullptr) {
579 TQualifier blockQualifier;
580 blockQualifier.clear();
581 blockQualifier.storage = EvqUniform;
582 TType blockType(new TTypeList, *NewPoolTString(getGlobalUniformBlockName()), blockQualifier);
583 setUniformBlockDefaults(blockType);
584 globalUniformBlock = new TVariable(NewPoolTString(""), blockType, true);
585 firstNewMember = 0;
586 }
587
588 // Update with binding and set
589 globalUniformBlock->getWritableType().getQualifier().layoutBinding = globalUniformBinding;
590 globalUniformBlock->getWritableType().getQualifier().layoutSet = globalUniformSet;
591
592 // Add the requested member as a member to the global block.
593 TType* type = new TType;
594 type->shallowCopy(memberType);
595 type->setFieldName(memberName);
596 if (typeList)
597 type->setStruct(typeList);
598 TTypeLoc typeLoc = {type, loc};
599 globalUniformBlock->getType().getWritableStruct()->push_back(typeLoc);
600
601 // Insert into the symbol table.
602 if (firstNewMember == 0) {
603 // This is the first request; we need a normal symbol table insert
604 if (symbolTable.insert(*globalUniformBlock))
605 trackLinkage(*globalUniformBlock);
606 else
607 error(loc, "failed to insert the global constant buffer", "uniform", "");
608 } else {
609 // This is a follow-on request; we need to amend the first insert
610 symbolTable.amend(*globalUniformBlock, firstNewMember);
611 }
612
613 ++firstNewMember;
614}
615
616void TParseContextBase::finish()
617{
618 if (parsingBuiltins)
619 return;
620
621 // Transfer the linkage symbols to AST nodes, preserving order.
622 TIntermAggregate* linkage = new TIntermAggregate;
623 for (auto i = linkageSymbols.begin(); i != linkageSymbols.end(); ++i)
624 intermediate.addSymbolLinkageNode(linkage, **i);
625 intermediate.addSymbolLinkageNodes(linkage, getLanguage(), symbolTable);
626}
627
628} // end namespace glslang
629