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