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, TType& t) : unionArray(cUnion), type(t),
44 constructorType(constructType), singleConstantParam(singleConstParam), infoSink(sink), error(false), isMatrix(false),
45 matrixCols(0), matrixRows(0) { index = 0; tOp = EOpNull;}
47 constUnion *unionArray;
50 TOperator constructorType;
51 bool singleConstantParam;
54 int size; // size of the constructor ( 4 for vec4)
61 // The rest of the file are the traversal functions. The last one
62 // is the one that starts the traversal.
64 // Return true from interior nodes to have the external traversal
65 // continue on to children. If you process children yourself,
69 void ParseSymbol(TIntermSymbol* node, TIntermTraverser* it)
71 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
72 oit->infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
77 bool ParseBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
79 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
81 TStorageQualifier qualifier = node->getType().getQualifier().storage;
83 if (qualifier != EvqConst) {
84 const int maxSize = 200;
86 snprintf(buf, maxSize, "'constructor' : assigning non-constant to %s", oit->type.getCompleteString().c_str());
87 oit->infoSink.info.message(EPrefixError, buf, node->getLine());
93 oit->infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
98 bool ParseUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
100 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
102 const int maxSize = 200;
104 snprintf(buf, maxSize, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
105 oit->infoSink.info.message(EPrefixError, buf, node->getLine());
111 bool ParseAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
113 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
115 if (!node->isConstructor() && node->getOp() != EOpComma) {
116 const int maxSize = 200;
118 snprintf(buf, maxSize, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
119 oit->infoSink.info.message(EPrefixError, buf, node->getLine());
125 if (node->getSequence().size() == 0) {
131 bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
133 oit->singleConstantParam = true;
134 oit->constructorType = node->getOp();
135 oit->size = node->getType().getObjectSize();
137 if (node->getType().isMatrix()) {
138 oit->isMatrix = true;
139 oit->matrixCols = node->getType().getMatrixCols();
140 oit->matrixRows = node->getType().getMatrixRows();
144 for (TIntermSequence::iterator p = node->getSequence().begin();
145 p != node->getSequence().end(); p++) {
147 if (node->getOp() == EOpComma)
154 oit->singleConstantParam = false;
155 oit->constructorType = EOpNull;
157 oit->isMatrix = false;
165 bool ParseSelection(bool /* preVisit */, TIntermSelection* node, TIntermTraverser* it)
167 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
168 oit->infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
173 void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
175 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
176 constUnion* leftUnionArray = oit->unionArray;
177 int instanceSize = oit->type.getObjectSize();
179 if (oit->index >= instanceSize)
182 if (!oit->singleConstantParam) {
183 int size = node->getType().getObjectSize();
185 constUnion *rightUnionArray = node->getUnionArrayPointer();
186 for (int i=0; i < size; i++) {
187 if (oit->index >= instanceSize)
189 leftUnionArray[oit->index] = rightUnionArray[i];
194 int size, totalSize, matrixCols, matrixRows;
195 bool isMatrix = false;
197 matrixCols = oit->matrixCols;
198 matrixRows = oit->matrixRows;
199 isMatrix = oit->isMatrix;
200 totalSize = oit->index + size;
201 constUnion *rightUnionArray = node->getUnionArrayPointer();
204 for (int i = oit->index; i < totalSize; i++) {
205 if (i >= instanceSize)
208 leftUnionArray[i] = rightUnionArray[count];
212 if (node->getType().getObjectSize() > 1)
215 } else { // for matrix constructors
217 int index = oit->index;
218 for (int i = index; i < totalSize; i++) {
219 if (i >= instanceSize)
221 if (index - i == 0 || (i - index) % (matrixRows + 1) == 0 )
222 leftUnionArray[i] = rightUnionArray[count];
224 leftUnionArray[i].setFConst(0.0f);
228 if (node->getType().getObjectSize() > 1)
235 bool ParseLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it)
237 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
238 oit->infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
244 bool ParseBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it)
246 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
247 oit->infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
254 // This function is the one to call externally to start the traversal.
255 // Individual functions can be initialized to 0 to skip processing of that
256 // type of node. It's children will still be processed.
258 bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, constUnion* unionArray, TOperator constructorType, TType t, bool singleConstantParam)
263 TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, t);
265 it.visitAggregate = ParseAggregate;
266 it.visitBinary = ParseBinary;
267 it.visitConstantUnion = ParseConstantUnion;
268 it.visitSelection = ParseSelection;
269 it.visitSymbol = ParseSymbol;
270 it.visitUnary = ParseUnary;
271 it.visitLoop = ParseLoop;
272 it.visitBranch = ParseBranch;