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