• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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