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 #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.
rValueErrorCheck(const TSourceLoc & loc,const char * op,TIntermTyped * node)215 void 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.
trackLinkage(TSymbol & symbol)247 void 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.
checkIndex(const TSourceLoc & loc,const TType & type,int & index)255 void 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).
makeEditable(TSymbol * & symbol)282 void 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).
getEditableVariable(const char * name)297 TVariable* 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 //
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)339 const 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 //
parseSwizzleSelector(const TSourceLoc & loc,const TString & compString,int vecSize,TSwizzleSelectors<TVectorSelector> & selector)475 void 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 //
growGlobalUniformBlock(const TSourceLoc & loc,TType & memberType,const TString & memberName,TTypeList * typeList)575 void 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 
finish()616 void 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