2 //Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
5 //Redistribution and use in source and binary forms, with or without
6 //modification, are permitted provided that the following conditions
9 // Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
12 // Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following
14 // disclaimer in the documentation and/or other materials provided
15 // with the distribution.
17 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
18 // contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
21 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 //POSSIBILITY OF SUCH DAMAGE.
35 #include "ParseHelper.h"
38 // Use this class to carry along data from node to node in
41 class TConstTraverser : public TIntermTraverser {
43 TConstTraverser(constUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t) : unionArray(cUnion), type(t),
44 constructorType(constructType), singleConstantParam(singleConstParam), infoSink(sink), symbolTable(symTable), error(false), isMatrix(false),
45 matrixCols(0), matrixRows(0) { index = 0; tOp = EOpNull;}
47 constUnion *unionArray;
50 TOperator constructorType;
51 bool singleConstantParam;
53 TSymbolTable& symbolTable;
55 int size; // size of the constructor ( 4 for vec4)
62 // The rest of the file are the traversal functions. The last one
63 // is the one that starts the traversal.
65 // Return true from interior nodes to have the external traversal
66 // continue on to children. If you process children yourself,
70 void ParseSymbol(TIntermSymbol* node, TIntermTraverser* it)
72 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
73 oit->infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
78 bool ParseBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
80 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
82 TStorageQualifier qualifier = node->getType().getQualifier().storage;
84 if (qualifier != EvqConst) {
85 const int maxSize = 200;
87 snprintf(buf, maxSize, "'constructor' : assigning non-constant to %s", oit->type.getCompleteString().c_str());
88 oit->infoSink.info.message(EPrefixError, buf, node->getLine());
94 oit->infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
99 bool ParseUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
101 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
103 const int maxSize = 200;
105 snprintf(buf, maxSize, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
106 oit->infoSink.info.message(EPrefixError, buf, node->getLine());
112 bool ParseAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
114 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
116 if (!node->isConstructor() && node->getOp() != EOpComma) {
117 const int maxSize = 200;
119 snprintf(buf, maxSize, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
120 oit->infoSink.info.message(EPrefixError, buf, node->getLine());
126 if (node->getSequence().size() == 0) {
132 bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
134 oit->singleConstantParam = true;
135 oit->constructorType = node->getOp();
136 oit->size = node->getType().getObjectSize();
138 if (node->getType().isMatrix()) {
139 oit->isMatrix = true;
140 oit->matrixCols = node->getType().getMatrixCols();
141 oit->matrixRows = node->getType().getMatrixRows();
145 for (TIntermSequence::iterator p = node->getSequence().begin();
146 p != node->getSequence().end(); p++) {
148 if (node->getOp() == EOpComma)
155 oit->singleConstantParam = false;
156 oit->constructorType = EOpNull;
158 oit->isMatrix = false;
166 bool ParseSelection(bool /* preVisit */, TIntermSelection* node, TIntermTraverser* it)
168 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
169 oit->infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
174 void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
176 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
177 constUnion* leftUnionArray = oit->unionArray;
178 int instanceSize = oit->type.getObjectSize();
180 if (oit->index >= instanceSize)
183 if (!oit->singleConstantParam) {
184 int size = node->getType().getObjectSize();
186 constUnion *rightUnionArray = node->getUnionArrayPointer();
187 for (int i=0; i < size; i++) {
188 if (oit->index >= instanceSize)
190 leftUnionArray[oit->index] = rightUnionArray[i];
195 int size, totalSize, matrixCols, matrixRows;
196 bool isMatrix = false;
198 matrixCols = oit->matrixCols;
199 matrixRows = oit->matrixRows;
200 isMatrix = oit->isMatrix;
201 totalSize = oit->index + size;
202 constUnion *rightUnionArray = node->getUnionArrayPointer();
205 for (int i = oit->index; i < totalSize; i++) {
206 if (i >= instanceSize)
209 leftUnionArray[i] = rightUnionArray[count];
213 if (node->getType().getObjectSize() > 1)
216 } else { // for matrix constructors
218 int index = oit->index;
219 for (int i = index; i < totalSize; i++) {
220 if (i >= instanceSize)
222 if (index - i == 0 || (i - index) % (matrixRows + 1) == 0 )
223 leftUnionArray[i] = rightUnionArray[count];
225 leftUnionArray[i].setFConst(0.0f);
229 if (node->getType().getObjectSize() > 1)
236 bool ParseLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it)
238 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
239 oit->infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
245 bool ParseBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it)
247 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
248 oit->infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
255 // This function is the one to call externally to start the traversal.
256 // Individual functions can be initialized to 0 to skip processing of that
257 // type of node. It's children will still be processed.
259 bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, constUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
264 TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);
266 it.visitAggregate = ParseAggregate;
267 it.visitBinary = ParseBinary;
268 it.visitConstantUnion = ParseConstantUnion;
269 it.visitSelection = ParseSelection;
270 it.visitSymbol = ParseSymbol;
271 it.visitUnary = ParseUnary;
272 it.visitLoop = ParseLoop;
273 it.visitBranch = ParseBranch;