2 //Copyright (C) 2013 LunarG, Inc.
\r
4 //All rights reserved.
\r
6 //Redistribution and use in source and binary forms, with or without
\r
7 //modification, are permitted provided that the following conditions
\r
10 // Redistributions of source code must retain the above copyright
\r
11 // notice, this list of conditions and the following disclaimer.
\r
13 // Redistributions in binary form must reproduce the above
\r
14 // copyright notice, this list of conditions and the following
\r
15 // disclaimer in the documentation and/or other materials provided
\r
16 // with the distribution.
\r
18 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
\r
19 // contributors may be used to endorse or promote products derived
\r
20 // from this software without specific prior written permission.
\r
22 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
\r
23 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
\r
24 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
\r
25 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
\r
26 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
27 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
\r
28 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
\r
29 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
\r
30 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
\r
31 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
\r
32 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
\r
33 //POSSIBILITY OF SUCH DAMAGE.
\r
37 // Do sub tree walks for
\r
38 // 1) inductive loop bodies to see if the inductive variable is modified
\r
39 // 2) array-index expressions to see if they are "constant-index-expression"
\r
41 // These are per Appendix A of ES 2.0:
\r
43 // "Within the body of the loop, the loop index is not statically assigned to nor is it used as the
\r
44 // argument to a function out or inout parameter."
\r
46 // "The following are constant-index-expressions:
\r
47 // - Constant expressions
\r
48 // - Loop indices as defined in section 4
\r
49 // - Expressions composed of both of the above"
\r
51 // N.B.: assuming the last rule excludes function calls
\r
54 #include "ParseHelper.h"
\r
59 // The inductive loop-body traverser.
\r
61 // Just look at things that might modify the loop index.
\r
64 class TInductiveTraverser : public TIntermTraverser {
\r
66 TInductiveTraverser(int id, TSymbolTable& st)
\r
67 : loopId(id), symbolTable(st), bad(false) { }
\r
69 virtual bool visitBinary(TVisit, TIntermBinary* node);
\r
70 virtual bool visitUnary(TVisit, TIntermUnary* node);
\r
71 virtual bool visitAggregate(TVisit, TIntermAggregate* node);
\r
73 int loopId; // unique ID of the symbol that's the loop inductive variable
\r
74 TSymbolTable& symbolTable;
\r
79 TInductiveTraverser(TInductiveTraverser&);
\r
80 TInductiveTraverser& operator=(TInductiveTraverser&);
\r
83 // check binary operations for those modifying the loop index
\r
84 bool TInductiveTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
\r
86 if (node->modifiesState() && node->getLeft()->getAsSymbolNode() &&
\r
87 node->getLeft()->getAsSymbolNode()->getId() == loopId) {
\r
89 badLoc = node->getLoc();
\r
95 // check unary operations for those modifying the loop index
\r
96 bool TInductiveTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
\r
98 if (node->modifiesState() && node->getOperand()->getAsSymbolNode() &&
\r
99 node->getOperand()->getAsSymbolNode()->getId() == loopId) {
\r
101 badLoc = node->getLoc();
\r
107 // check function calls for arguments modifying the loop index
\r
108 bool TInductiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
\r
110 if (node->getOp() == EOpFunctionCall) {
\r
111 // see if an out or inout argument is the loop index
\r
112 const TIntermSequence& args = node->getSequence();
\r
113 for (int i = 0; i < (int)args.size(); ++i) {
\r
114 if (args[i]->getAsSymbolNode() && args[i]->getAsSymbolNode()->getId() == loopId) {
\r
115 TSymbol* function = symbolTable.find(node->getName());
\r
116 const TType* type = (*function->getAsFunction())[i].type;
\r
117 if (type->getQualifier().storage == EvqOut ||
\r
118 type->getQualifier().storage == EvqInOut) {
\r
120 badLoc = node->getLoc();
\r
130 // External function to call for loop check.
\r
132 void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, int loopId, TSymbolTable& symbolTable)
\r
134 TInductiveTraverser it(loopId, symbolTable);
\r
139 body->traverse(&it);
\r
142 error(it.badLoc, "inductive loop index modified", "limitations", "");
\r
146 // The "constant-index-expression" tranverser.
\r
148 // Just look at things that can form an index.
\r
151 class TIndexTraverser : public TIntermTraverser {
\r
153 TIndexTraverser(const TIdSetType& ids) : inductiveLoopIds(ids), bad(false) { }
\r
154 virtual void visitSymbol(TIntermSymbol* symbol);
\r
155 virtual bool visitAggregate(TVisit, TIntermAggregate* node);
\r
156 const TIdSetType& inductiveLoopIds;
\r
161 TIndexTraverser(TIndexTraverser&);
\r
162 TIndexTraverser& operator=(TIndexTraverser&);
\r
165 // make sure symbols are inductive-loop indexes
\r
166 void TIndexTraverser::visitSymbol(TIntermSymbol* symbol)
\r
168 if (inductiveLoopIds.find(symbol->getId()) == inductiveLoopIds.end()) {
\r
170 badLoc = symbol->getLoc();
\r
174 // check for function calls, assuming they are bad; spec. doesn't really say
\r
175 bool TIndexTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
\r
177 if (node->getOp() == EOpFunctionCall) {
\r
179 badLoc = node->getLoc();
\r
186 // External function to call for loop check.
\r
188 void TParseContext::constantIndexExpressionCheck(TIntermNode* index)
\r
190 TIndexTraverser it(inductiveLoopIds);
\r
192 index->traverse(&it);
\r
195 error(it.badLoc, "Non-constant-index-expression", "limitations", "");
\r
198 } // end namespace glslang
\r