LCOV - code coverage report
Current view: top level - gfx/angle/src/compiler/translator - QualifierTypes.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 330 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 26 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
       3             : // Use of this source code is governed by a BSD-style license that can be
       4             : // found in the LICENSE file.
       5             : //
       6             : 
       7             : #include "compiler/translator/QualifierTypes.h"
       8             : 
       9             : #include "compiler/translator/Diagnostics.h"
      10             : 
      11             : #include <algorithm>
      12             : 
      13             : namespace sh
      14             : {
      15             : 
      16             : namespace
      17             : {
      18             : 
      19             : // GLSL ES 3.10 does not impose a strict order on type qualifiers and allows multiple layout
      20             : // declarations.
      21             : // GLSL ES 3.10 Revision 4, 4.10 Order of Qualification
      22           0 : bool AreTypeQualifierChecksRelaxed(int shaderVersion)
      23             : {
      24           0 :     return shaderVersion >= 310;
      25             : }
      26             : 
      27           0 : bool IsScopeQualifier(TQualifier qualifier)
      28             : {
      29           0 :     return qualifier == EvqGlobal || qualifier == EvqTemporary;
      30             : }
      31             : 
      32           0 : bool IsScopeQualifierWrapper(const TQualifierWrapperBase *qualifier)
      33             : {
      34           0 :     if (qualifier->getType() != QtStorage)
      35           0 :         return false;
      36             :     const TStorageQualifierWrapper *storageQualifier =
      37           0 :         static_cast<const TStorageQualifierWrapper *>(qualifier);
      38           0 :     TQualifier q = storageQualifier->getQualifier();
      39           0 :     return IsScopeQualifier(q);
      40             : }
      41             : 
      42             : // Returns true if the invariant for the qualifier sequence holds
      43           0 : bool IsInvariantCorrect(const TTypeQualifierBuilder::QualifierSequence &qualifiers)
      44             : {
      45             :     // We should have at least one qualifier.
      46             :     // The first qualifier always tells the scope.
      47           0 :     return qualifiers.size() >= 1 && IsScopeQualifierWrapper(qualifiers[0]);
      48             : }
      49             : 
      50             : // Returns true if there are qualifiers which have been specified multiple times
      51             : // If areQualifierChecksRelaxed is set to true, then layout qualifier repetition is allowed.
      52           0 : bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qualifiers,
      53             :                             bool areQualifierChecksRelaxed,
      54             :                             std::string *errorMessage)
      55             : {
      56           0 :     bool invariantFound     = false;
      57           0 :     bool precisionFound     = false;
      58           0 :     bool layoutFound        = false;
      59           0 :     bool interpolationFound = false;
      60             : 
      61           0 :     unsigned int locationsSpecified = 0;
      62           0 :     bool isOut                      = false;
      63             : 
      64             :     // The iteration starts from one since the first qualifier only reveals the scope of the
      65             :     // expression. It is inserted first whenever the sequence gets created.
      66           0 :     for (size_t i = 1; i < qualifiers.size(); ++i)
      67             :     {
      68           0 :         switch (qualifiers[i]->getType())
      69             :         {
      70             :             case QtInvariant:
      71             :             {
      72           0 :                 if (invariantFound)
      73             :                 {
      74           0 :                     *errorMessage = "The invariant qualifier specified multiple times.";
      75           0 :                     return true;
      76             :                 }
      77           0 :                 invariantFound = true;
      78           0 :                 break;
      79             :             }
      80             :             case QtPrecision:
      81             :             {
      82           0 :                 if (precisionFound)
      83             :                 {
      84           0 :                     *errorMessage = "The precision qualifier specified multiple times.";
      85           0 :                     return true;
      86             :                 }
      87           0 :                 precisionFound = true;
      88           0 :                 break;
      89             :             }
      90             :             case QtLayout:
      91             :             {
      92           0 :                 if (layoutFound && !areQualifierChecksRelaxed)
      93             :                 {
      94           0 :                     *errorMessage = "The layout qualifier specified multiple times.";
      95           0 :                     return true;
      96             :                 }
      97           0 :                 if (invariantFound && !areQualifierChecksRelaxed)
      98             :                 {
      99             :                     // This combination is not correct according to the syntax specified in the
     100             :                     // formal grammar in the ESSL 3.00 spec. In ESSL 3.10 the grammar does not have
     101             :                     // a similar restriction.
     102             :                     *errorMessage =
     103             :                         "The layout qualifier and invariant qualifier cannot coexist in the same "
     104           0 :                         "declaration according to the grammar.";
     105           0 :                     return true;
     106             :                 }
     107           0 :                 layoutFound = true;
     108             :                 const TLayoutQualifier &currentQualifier =
     109           0 :                     static_cast<const TLayoutQualifierWrapper *>(qualifiers[i])->getQualifier();
     110           0 :                 locationsSpecified += currentQualifier.locationsSpecified;
     111           0 :                 break;
     112             :             }
     113             :             case QtInterpolation:
     114             :             {
     115             :                 // 'centroid' is treated as a storage qualifier
     116             :                 // 'flat centroid' will be squashed to 'flat'
     117             :                 // 'smooth centroid' will be squashed to 'centroid'
     118           0 :                 if (interpolationFound)
     119             :                 {
     120           0 :                     *errorMessage = "The interpolation qualifier specified multiple times.";
     121           0 :                     return true;
     122             :                 }
     123           0 :                 interpolationFound = true;
     124           0 :                 break;
     125             :             }
     126             :             case QtStorage:
     127             :             {
     128             :                 // Go over all of the storage qualifiers up until the current one and check for
     129             :                 // repetitions.
     130             :                 TQualifier currentQualifier =
     131           0 :                     static_cast<const TStorageQualifierWrapper *>(qualifiers[i])->getQualifier();
     132           0 :                 if (currentQualifier == EvqVertexOut || currentQualifier == EvqFragmentOut)
     133             :                 {
     134           0 :                     isOut = true;
     135             :                 }
     136           0 :                 for (size_t j = 1; j < i; ++j)
     137             :                 {
     138           0 :                     if (qualifiers[j]->getType() == QtStorage)
     139             :                     {
     140             :                         const TStorageQualifierWrapper *previousQualifierWrapper =
     141           0 :                             static_cast<const TStorageQualifierWrapper *>(qualifiers[j]);
     142           0 :                         TQualifier previousQualifier = previousQualifierWrapper->getQualifier();
     143           0 :                         if (currentQualifier == previousQualifier)
     144             :                         {
     145           0 :                             *errorMessage = previousQualifierWrapper->getQualifierString().c_str();
     146           0 :                             *errorMessage += " specified multiple times";
     147           0 :                             return true;
     148             :                         }
     149             :                     }
     150             :                 }
     151           0 :                 break;
     152             :             }
     153             :             case QtMemory:
     154             :             {
     155             :                 // Go over all of the memory qualifiers up until the current one and check for
     156             :                 // repetitions.
     157             :                 // Having both readonly and writeonly in a sequence is valid.
     158             :                 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
     159             :                 TQualifier currentQualifier =
     160           0 :                     static_cast<const TMemoryQualifierWrapper *>(qualifiers[i])->getQualifier();
     161           0 :                 for (size_t j = 1; j < i; ++j)
     162             :                 {
     163           0 :                     if (qualifiers[j]->getType() == QtMemory)
     164             :                     {
     165             :                         const TMemoryQualifierWrapper *previousQualifierWrapper =
     166           0 :                             static_cast<const TMemoryQualifierWrapper *>(qualifiers[j]);
     167           0 :                         TQualifier previousQualifier = previousQualifierWrapper->getQualifier();
     168           0 :                         if (currentQualifier == previousQualifier)
     169             :                         {
     170           0 :                             *errorMessage = previousQualifierWrapper->getQualifierString().c_str();
     171           0 :                             *errorMessage += " specified multiple times";
     172           0 :                             return true;
     173             :                         }
     174             :                     }
     175             :                 }
     176           0 :                 break;
     177             :             }
     178             :             default:
     179           0 :                 UNREACHABLE();
     180             :         }
     181             :     }
     182             : 
     183           0 :     if (locationsSpecified > 1 && isOut)
     184             :     {
     185             :         // GLSL ES 3.00.6 section 4.3.8.2 Output Layout Qualifiers
     186             :         // GLSL ES 3.10 section 4.4.2 Output Layout Qualifiers
     187             :         // "The qualifier may appear at most once within a declaration."
     188           0 :         *errorMessage = "Output layout location specified multiple times.";
     189           0 :         return true;
     190             :     }
     191             : 
     192           0 :     return false;
     193             : }
     194             : 
     195             : // GLSL ES 3.00_6, 4.7 Order of Qualification
     196             : // The correct order of qualifiers is:
     197             : // invariant-qualifier interpolation-qualifier storage-qualifier precision-qualifier
     198             : // layout-qualifier has to be before storage-qualifier.
     199           0 : bool AreQualifiersInOrder(const TTypeQualifierBuilder::QualifierSequence &qualifiers,
     200             :                           std::string *errorMessage)
     201             : {
     202           0 :     bool foundInterpolation = false;
     203           0 :     bool foundStorage       = false;
     204           0 :     bool foundPrecision     = false;
     205           0 :     for (size_t i = 1; i < qualifiers.size(); ++i)
     206             :     {
     207           0 :         switch (qualifiers[i]->getType())
     208             :         {
     209             :             case QtInvariant:
     210           0 :                 if (foundInterpolation || foundStorage || foundPrecision)
     211             :                 {
     212           0 :                     *errorMessage = "The invariant qualifier has to be first in the expression.";
     213           0 :                     return false;
     214             :                 }
     215           0 :                 break;
     216             :             case QtInterpolation:
     217           0 :                 if (foundStorage)
     218             :                 {
     219           0 :                     *errorMessage = "Storage qualifiers have to be after interpolation qualifiers.";
     220           0 :                     return false;
     221             :                 }
     222           0 :                 else if (foundPrecision)
     223             :                 {
     224             :                     *errorMessage =
     225           0 :                         "Precision qualifiers have to be after interpolation qualifiers.";
     226           0 :                     return false;
     227             :                 }
     228           0 :                 foundInterpolation = true;
     229           0 :                 break;
     230             :             case QtLayout:
     231           0 :                 if (foundStorage)
     232             :                 {
     233           0 :                     *errorMessage = "Storage qualifiers have to be after layout qualifiers.";
     234           0 :                     return false;
     235             :                 }
     236           0 :                 else if (foundPrecision)
     237             :                 {
     238           0 :                     *errorMessage = "Precision qualifiers have to be after layout qualifiers.";
     239           0 :                     return false;
     240             :                 }
     241           0 :                 break;
     242             :             case QtStorage:
     243           0 :                 if (foundPrecision)
     244             :                 {
     245           0 :                     *errorMessage = "Precision qualifiers have to be after storage qualifiers.";
     246           0 :                     return false;
     247             :                 }
     248           0 :                 foundStorage = true;
     249           0 :                 break;
     250             :             case QtMemory:
     251           0 :                 if (foundPrecision)
     252             :                 {
     253           0 :                     *errorMessage = "Precision qualifiers have to be after memory qualifiers.";
     254           0 :                     return false;
     255             :                 }
     256           0 :                 break;
     257             :             case QtPrecision:
     258           0 :                 foundPrecision = true;
     259           0 :                 break;
     260             :             default:
     261           0 :                 UNREACHABLE();
     262             :         }
     263             :     }
     264           0 :     return true;
     265             : }
     266             : 
     267             : struct QualifierComparator
     268             : {
     269           0 :     bool operator()(const TQualifierWrapperBase *q1, const TQualifierWrapperBase *q2)
     270             :     {
     271           0 :         return q1->getRank() < q2->getRank();
     272             :     }
     273             : };
     274             : 
     275           0 : void SortSequence(TTypeQualifierBuilder::QualifierSequence &qualifiers)
     276             : {
     277             :     // We need a stable sorting algorithm since the order of layout-qualifier declarations matter.
     278             :     // The sorting starts from index 1, instead of 0, since the element at index 0 tells the scope
     279             :     // and we always want it to be first.
     280           0 :     std::stable_sort(qualifiers.begin() + 1, qualifiers.end(), QualifierComparator());
     281           0 : }
     282             : 
     283             : // Handles the joining of storage qualifiers for variables.
     284           0 : bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier)
     285             : {
     286           0 :     switch (*joinedQualifier)
     287             :     {
     288             :         case EvqGlobal:
     289           0 :             *joinedQualifier = storageQualifier;
     290           0 :             break;
     291             :         case EvqTemporary:
     292             :         {
     293           0 :             switch (storageQualifier)
     294             :             {
     295             :                 case EvqConst:
     296           0 :                     *joinedQualifier = storageQualifier;
     297           0 :                     break;
     298             :                 default:
     299           0 :                     return false;
     300             :             }
     301           0 :             break;
     302             :         }
     303             :         case EvqSmooth:
     304             :         {
     305           0 :             switch (storageQualifier)
     306             :             {
     307             :                 case EvqCentroid:
     308           0 :                     *joinedQualifier = EvqCentroid;
     309           0 :                     break;
     310             :                 case EvqVertexOut:
     311           0 :                     *joinedQualifier = EvqSmoothOut;
     312           0 :                     break;
     313             :                 case EvqFragmentIn:
     314           0 :                     *joinedQualifier = EvqSmoothIn;
     315           0 :                     break;
     316             :                 default:
     317           0 :                     return false;
     318             :             }
     319           0 :             break;
     320             :         }
     321             :         case EvqFlat:
     322             :         {
     323           0 :             switch (storageQualifier)
     324             :             {
     325             :                 case EvqCentroid:
     326           0 :                     *joinedQualifier = EvqFlat;
     327           0 :                     break;
     328             :                 case EvqVertexOut:
     329           0 :                     *joinedQualifier = EvqFlatOut;
     330           0 :                     break;
     331             :                 case EvqFragmentIn:
     332           0 :                     *joinedQualifier = EvqFlatIn;
     333           0 :                     break;
     334             :                 default:
     335           0 :                     return false;
     336             :             }
     337           0 :             break;
     338             :         }
     339             :         case EvqCentroid:
     340             :         {
     341           0 :             switch (storageQualifier)
     342             :             {
     343             :                 case EvqVertexOut:
     344           0 :                     *joinedQualifier = EvqCentroidOut;
     345           0 :                     break;
     346             :                 case EvqFragmentIn:
     347           0 :                     *joinedQualifier = EvqCentroidIn;
     348           0 :                     break;
     349             :                 default:
     350           0 :                     return false;
     351             :             }
     352           0 :             break;
     353             :         }
     354             :         default:
     355           0 :             return false;
     356             :     }
     357           0 :     return true;
     358             : }
     359             : 
     360             : // Handles the joining of storage qualifiers for a parameter in a function.
     361           0 : bool JoinParameterStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier)
     362             : {
     363           0 :     switch (*joinedQualifier)
     364             :     {
     365             :         case EvqTemporary:
     366           0 :             *joinedQualifier = storageQualifier;
     367           0 :             break;
     368             :         case EvqConst:
     369             :         {
     370           0 :             switch (storageQualifier)
     371             :             {
     372             :                 case EvqIn:
     373           0 :                     *joinedQualifier = EvqConstReadOnly;
     374           0 :                     break;
     375             :                 default:
     376           0 :                     return false;
     377             :             }
     378           0 :             break;
     379             :         }
     380             :         default:
     381           0 :             return false;
     382             :     }
     383           0 :     return true;
     384             : }
     385             : 
     386           0 : bool JoinMemoryQualifier(TMemoryQualifier *joinedMemoryQualifier, TQualifier memoryQualifier)
     387             : {
     388           0 :     switch (memoryQualifier)
     389             :     {
     390             :         case EvqReadOnly:
     391           0 :             joinedMemoryQualifier->readonly = true;
     392           0 :             break;
     393             :         case EvqWriteOnly:
     394           0 :             joinedMemoryQualifier->writeonly = true;
     395           0 :             break;
     396             :         case EvqCoherent:
     397           0 :             joinedMemoryQualifier->coherent = true;
     398           0 :             break;
     399             :         case EvqRestrict:
     400           0 :             joinedMemoryQualifier->restrictQualifier = true;
     401           0 :             break;
     402             :         case EvqVolatile:
     403             :             // Variables having the volatile qualifier are automatcally treated as coherent as well.
     404             :             // GLSL ES 3.10, Revision 4, 4.9 Memory Access Qualifiers
     405           0 :             joinedMemoryQualifier->volatileQualifier = true;
     406           0 :             joinedMemoryQualifier->coherent          = true;
     407           0 :             break;
     408             :         default:
     409           0 :             UNREACHABLE();
     410             :     }
     411           0 :     return true;
     412             : }
     413             : 
     414           0 : TTypeQualifier GetVariableTypeQualifierFromSortedSequence(
     415             :     const TTypeQualifierBuilder::QualifierSequence &sortedSequence,
     416             :     TDiagnostics *diagnostics)
     417             : {
     418             :     TTypeQualifier typeQualifier(
     419           0 :         static_cast<const TStorageQualifierWrapper *>(sortedSequence[0])->getQualifier(),
     420           0 :         sortedSequence[0]->getLine());
     421           0 :     for (size_t i = 1; i < sortedSequence.size(); ++i)
     422             :     {
     423           0 :         const TQualifierWrapperBase *qualifier = sortedSequence[i];
     424           0 :         bool isQualifierValid                  = false;
     425           0 :         switch (qualifier->getType())
     426             :         {
     427             :             case QtInvariant:
     428           0 :                 isQualifierValid        = true;
     429           0 :                 typeQualifier.invariant = true;
     430           0 :                 break;
     431             :             case QtInterpolation:
     432             :             {
     433           0 :                 switch (typeQualifier.qualifier)
     434             :                 {
     435             :                     case EvqGlobal:
     436           0 :                         isQualifierValid = true;
     437           0 :                         typeQualifier.qualifier =
     438             :                             static_cast<const TInterpolationQualifierWrapper *>(qualifier)
     439           0 :                                 ->getQualifier();
     440           0 :                         break;
     441             :                     default:
     442           0 :                         isQualifierValid = false;
     443             :                 }
     444           0 :                 break;
     445             :             }
     446             :             case QtLayout:
     447             :             {
     448             :                 const TLayoutQualifierWrapper *layoutQualifierWrapper =
     449           0 :                     static_cast<const TLayoutQualifierWrapper *>(qualifier);
     450           0 :                 isQualifierValid              = true;
     451             :                 typeQualifier.layoutQualifier = sh::JoinLayoutQualifiers(
     452           0 :                     typeQualifier.layoutQualifier, layoutQualifierWrapper->getQualifier(),
     453           0 :                     layoutQualifierWrapper->getLine(), diagnostics);
     454           0 :                 break;
     455             :             }
     456             :             case QtStorage:
     457           0 :                 isQualifierValid = JoinVariableStorageQualifier(
     458             :                     &typeQualifier.qualifier,
     459           0 :                     static_cast<const TStorageQualifierWrapper *>(qualifier)->getQualifier());
     460           0 :                 break;
     461             :             case QtPrecision:
     462           0 :                 isQualifierValid = true;
     463           0 :                 typeQualifier.precision =
     464           0 :                     static_cast<const TPrecisionQualifierWrapper *>(qualifier)->getQualifier();
     465           0 :                 ASSERT(typeQualifier.precision != EbpUndefined);
     466           0 :                 break;
     467             :             case QtMemory:
     468           0 :                 isQualifierValid = JoinMemoryQualifier(
     469             :                     &typeQualifier.memoryQualifier,
     470           0 :                     static_cast<const TMemoryQualifierWrapper *>(qualifier)->getQualifier());
     471           0 :                 break;
     472             :             default:
     473           0 :                 UNREACHABLE();
     474             :         }
     475           0 :         if (!isQualifierValid)
     476             :         {
     477           0 :             const TString &qualifierString = qualifier->getQualifierString();
     478           0 :             diagnostics->error(qualifier->getLine(), "invalid qualifier combination",
     479           0 :                                qualifierString.c_str(), "");
     480           0 :             break;
     481             :         }
     482             :     }
     483           0 :     return typeQualifier;
     484             : }
     485             : 
     486           0 : TTypeQualifier GetParameterTypeQualifierFromSortedSequence(
     487             :     const TTypeQualifierBuilder::QualifierSequence &sortedSequence,
     488             :     TDiagnostics *diagnostics)
     489             : {
     490           0 :     TTypeQualifier typeQualifier(EvqTemporary, sortedSequence[0]->getLine());
     491           0 :     for (size_t i = 1; i < sortedSequence.size(); ++i)
     492             :     {
     493           0 :         const TQualifierWrapperBase *qualifier = sortedSequence[i];
     494           0 :         bool isQualifierValid                  = false;
     495           0 :         switch (qualifier->getType())
     496             :         {
     497             :             case QtInvariant:
     498             :             case QtInterpolation:
     499             :             case QtLayout:
     500           0 :                 break;
     501             :             case QtMemory:
     502           0 :                 isQualifierValid = JoinMemoryQualifier(
     503             :                     &typeQualifier.memoryQualifier,
     504           0 :                     static_cast<const TMemoryQualifierWrapper *>(qualifier)->getQualifier());
     505           0 :                 break;
     506             :             case QtStorage:
     507           0 :                 isQualifierValid = JoinParameterStorageQualifier(
     508             :                     &typeQualifier.qualifier,
     509           0 :                     static_cast<const TStorageQualifierWrapper *>(qualifier)->getQualifier());
     510           0 :                 break;
     511             :             case QtPrecision:
     512           0 :                 isQualifierValid = true;
     513           0 :                 typeQualifier.precision =
     514           0 :                     static_cast<const TPrecisionQualifierWrapper *>(qualifier)->getQualifier();
     515           0 :                 ASSERT(typeQualifier.precision != EbpUndefined);
     516           0 :                 break;
     517             :             default:
     518           0 :                 UNREACHABLE();
     519             :         }
     520           0 :         if (!isQualifierValid)
     521             :         {
     522           0 :             const TString &qualifierString = qualifier->getQualifierString();
     523           0 :             diagnostics->error(qualifier->getLine(), "invalid parameter qualifier",
     524           0 :                                qualifierString.c_str(), "");
     525           0 :             break;
     526             :         }
     527             :     }
     528             : 
     529           0 :     switch (typeQualifier.qualifier)
     530             :     {
     531             :         case EvqIn:
     532             :         case EvqConstReadOnly:  // const in
     533             :         case EvqOut:
     534             :         case EvqInOut:
     535           0 :             break;
     536             :         case EvqConst:
     537           0 :             typeQualifier.qualifier = EvqConstReadOnly;
     538           0 :             break;
     539             :         case EvqTemporary:
     540             :             // no qualifier has been specified, set it to EvqIn which is the default
     541           0 :             typeQualifier.qualifier = EvqIn;
     542           0 :             break;
     543             :         default:
     544           0 :             diagnostics->error(sortedSequence[0]->getLine(), "Invalid parameter qualifier ",
     545           0 :                                getQualifierString(typeQualifier.qualifier), "");
     546             :     }
     547           0 :     return typeQualifier;
     548             : }
     549             : }  // namespace
     550             : 
     551           0 : TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
     552             :                                       TLayoutQualifier rightQualifier,
     553             :                                       const TSourceLoc &rightQualifierLocation,
     554             :                                       TDiagnostics *diagnostics)
     555             : {
     556           0 :     TLayoutQualifier joinedQualifier = leftQualifier;
     557             : 
     558           0 :     if (rightQualifier.location != -1)
     559             :     {
     560           0 :         joinedQualifier.location = rightQualifier.location;
     561           0 :         ++joinedQualifier.locationsSpecified;
     562             :     }
     563           0 :     if (rightQualifier.matrixPacking != EmpUnspecified)
     564             :     {
     565           0 :         joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
     566             :     }
     567           0 :     if (rightQualifier.blockStorage != EbsUnspecified)
     568             :     {
     569           0 :         joinedQualifier.blockStorage = rightQualifier.blockStorage;
     570             :     }
     571             : 
     572           0 :     for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i)
     573             :     {
     574           0 :         if (rightQualifier.localSize[i] != -1)
     575             :         {
     576           0 :             if (joinedQualifier.localSize[i] != -1 &&
     577           0 :                 joinedQualifier.localSize[i] != rightQualifier.localSize[i])
     578             :             {
     579           0 :                 diagnostics->error(rightQualifierLocation,
     580             :                                    "Cannot have multiple different work group size specifiers",
     581           0 :                                    getWorkGroupSizeString(i), "");
     582             :             }
     583           0 :             joinedQualifier.localSize[i] = rightQualifier.localSize[i];
     584             :         }
     585             :     }
     586             : 
     587           0 :     if (rightQualifier.imageInternalFormat != EiifUnspecified)
     588             :     {
     589           0 :         joinedQualifier.imageInternalFormat = rightQualifier.imageInternalFormat;
     590             :     }
     591             : 
     592           0 :     return joinedQualifier;
     593             : }
     594             : 
     595           0 : unsigned int TInvariantQualifierWrapper::getRank() const
     596             : {
     597           0 :     return 0u;
     598             : }
     599             : 
     600           0 : unsigned int TInterpolationQualifierWrapper::getRank() const
     601             : {
     602           0 :     return 1u;
     603             : }
     604             : 
     605           0 : unsigned int TLayoutQualifierWrapper::getRank() const
     606             : {
     607           0 :     return 2u;
     608             : }
     609             : 
     610           0 : unsigned int TStorageQualifierWrapper::getRank() const
     611             : {
     612             :     // Force the 'centroid' auxilary storage qualifier to be always first among all storage
     613             :     // qualifiers.
     614           0 :     if (mStorageQualifier == EvqCentroid)
     615             :     {
     616           0 :         return 3u;
     617             :     }
     618             :     else
     619             :     {
     620           0 :         return 4u;
     621             :     }
     622             : }
     623             : 
     624           0 : unsigned int TMemoryQualifierWrapper::getRank() const
     625             : {
     626           0 :     return 4u;
     627             : }
     628             : 
     629           0 : unsigned int TPrecisionQualifierWrapper::getRank() const
     630             : {
     631           0 :     return 5u;
     632             : }
     633             : 
     634           0 : TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc)
     635             :     : layoutQualifier(TLayoutQualifier::create()),
     636             :       memoryQualifier(TMemoryQualifier::create()),
     637             :       precision(EbpUndefined),
     638             :       qualifier(scope),
     639             :       invariant(false),
     640           0 :       line(loc)
     641             : {
     642           0 :     ASSERT(IsScopeQualifier(qualifier));
     643           0 : }
     644             : 
     645           0 : TTypeQualifierBuilder::TTypeQualifierBuilder(const TStorageQualifierWrapper *scope,
     646           0 :                                              int shaderVersion)
     647           0 :     : mShaderVersion(shaderVersion)
     648             : {
     649           0 :     ASSERT(IsScopeQualifier(scope->getQualifier()));
     650           0 :     mQualifiers.push_back(scope);
     651           0 : }
     652             : 
     653           0 : void TTypeQualifierBuilder::appendQualifier(const TQualifierWrapperBase *qualifier)
     654             : {
     655           0 :     mQualifiers.push_back(qualifier);
     656           0 : }
     657             : 
     658           0 : bool TTypeQualifierBuilder::checkSequenceIsValid(TDiagnostics *diagnostics) const
     659             : {
     660           0 :     bool areQualifierChecksRelaxed = AreTypeQualifierChecksRelaxed(mShaderVersion);
     661           0 :     std::string errorMessage;
     662           0 :     if (HasRepeatingQualifiers(mQualifiers, areQualifierChecksRelaxed, &errorMessage))
     663             :     {
     664           0 :         diagnostics->error(mQualifiers[0]->getLine(), "qualifier sequence", errorMessage.c_str(),
     665           0 :                            "");
     666           0 :         return false;
     667             :     }
     668             : 
     669           0 :     if (!areQualifierChecksRelaxed && !AreQualifiersInOrder(mQualifiers, &errorMessage))
     670             :     {
     671           0 :         diagnostics->error(mQualifiers[0]->getLine(), "qualifier sequence", errorMessage.c_str(),
     672           0 :                            "");
     673           0 :         return false;
     674             :     }
     675             : 
     676           0 :     return true;
     677             : }
     678             : 
     679           0 : TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier(TDiagnostics *diagnostics) const
     680             : {
     681           0 :     ASSERT(IsInvariantCorrect(mQualifiers));
     682           0 :     ASSERT(static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier() ==
     683           0 :            EvqTemporary);
     684             : 
     685           0 :     if (!checkSequenceIsValid(diagnostics))
     686             :     {
     687           0 :         return TTypeQualifier(EvqTemporary, mQualifiers[0]->getLine());
     688             :     }
     689             : 
     690             :     // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so
     691             :     // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to
     692             :     // combine the qualifiers.
     693           0 :     if (AreTypeQualifierChecksRelaxed(mShaderVersion))
     694             :     {
     695             :         // Copy the qualifier sequence so that we can sort them.
     696           0 :         QualifierSequence sortedQualifierSequence = mQualifiers;
     697           0 :         SortSequence(sortedQualifierSequence);
     698           0 :         return GetParameterTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics);
     699             :     }
     700           0 :     return GetParameterTypeQualifierFromSortedSequence(mQualifiers, diagnostics);
     701             : }
     702             : 
     703           0 : TTypeQualifier TTypeQualifierBuilder::getVariableTypeQualifier(TDiagnostics *diagnostics) const
     704             : {
     705           0 :     ASSERT(IsInvariantCorrect(mQualifiers));
     706             : 
     707           0 :     if (!checkSequenceIsValid(diagnostics))
     708             :     {
     709             :         return TTypeQualifier(
     710           0 :             static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier(),
     711           0 :             mQualifiers[0]->getLine());
     712             :     }
     713             : 
     714             :     // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so
     715             :     // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to
     716             :     // combine the qualifiers.
     717           0 :     if (AreTypeQualifierChecksRelaxed(mShaderVersion))
     718             :     {
     719             :         // Copy the qualifier sequence so that we can sort them.
     720           0 :         QualifierSequence sortedQualifierSequence = mQualifiers;
     721           0 :         SortSequence(sortedQualifierSequence);
     722           0 :         return GetVariableTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics);
     723             :     }
     724           0 :     return GetVariableTypeQualifierFromSortedSequence(mQualifiers, diagnostics);
     725             : }
     726             : 
     727             : }  // namespace sh

Generated by: LCOV version 1.13