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), matrixSize(0) { index = 0; tOp = EOpNull;}
46 constUnion *unionArray;
49 TOperator constructorType;
50 bool singleConstantParam;
52 TSymbolTable& symbolTable;
54 int size; // size of the constructor ( 4 for vec4)
56 int matrixSize; // dimension of the matrix (nominal size and not the instance size)
60 // The rest of the file are the traversal functions. The last one
61 // is the one that starts the traversal.
63 // Return true from interior nodes to have the external traversal
64 // continue on to children. If you process children yourself,
68 void ParseSymbol(TIntermSymbol* node, TIntermTraverser* it)
70 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
71 oit->infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
76 bool ParseBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
78 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
80 TQualifier qualifier = node->getType().getQualifier();
82 if (qualifier != EvqConst) {
84 sprintf(buf, "'constructor' : assigning non-constant to %s", oit->type.getCompleteString().c_str());
85 oit->infoSink.info.message(EPrefixError, buf, node->getLine());
90 oit->infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
95 bool ParseUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
97 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
100 sprintf(buf, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
101 oit->infoSink.info.message(EPrefixError, buf, node->getLine());
106 bool ParseAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
108 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
110 if (!node->isConstructor() && node->getOp() != EOpComma) {
112 sprintf(buf, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
113 oit->infoSink.info.message(EPrefixError, buf, node->getLine());
118 if (node->getSequence().size() == 0) {
123 bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
126 oit->singleConstantParam = true;
127 oit->constructorType = node->getOp();
128 oit->size = node->getType().getObjectSize();
130 if (node->getType().isMatrix()) {
131 oit->isMatrix = true;
132 oit->matrixSize = node->getType().getNominalSize();
136 for (TIntermSequence::iterator p = node->getSequence().begin();
137 p != node->getSequence().end(); p++) {
139 if (node->getOp() == EOpComma)
146 oit->singleConstantParam = false;
147 oit->constructorType = EOpNull;
149 oit->isMatrix = false;
155 bool ParseSelection(bool /* preVisit */, TIntermSelection* node, TIntermTraverser* it)
157 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
158 oit->infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
163 void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
165 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
166 constUnion* leftUnionArray = oit->unionArray;
167 int instanceSize = oit->type.getObjectSize();
169 if (oit->index >= instanceSize)
172 if (!oit->singleConstantParam) {
173 int size = node->getType().getObjectSize();
175 constUnion *rightUnionArray = node->getUnionArrayPointer();
176 for (int i=0; i < size; i++) {
177 if (oit->index >= instanceSize)
179 leftUnionArray[oit->index] = rightUnionArray[i];
184 int size, totalSize, matrixSize;
185 bool isMatrix = false;
187 matrixSize = oit->matrixSize;
188 isMatrix = oit->isMatrix;
189 totalSize = oit->index + size ;
190 constUnion *rightUnionArray = node->getUnionArrayPointer();
193 for (int i = oit->index; i < totalSize; i++) {
194 if (i >= instanceSize)
197 leftUnionArray[i] = rightUnionArray[count];
201 if (node->getType().getObjectSize() > 1)
204 } else { // for matrix constructors
206 int index = oit->index;
207 for (int i = index; i < totalSize; i++) {
208 if (i >= instanceSize)
210 if (index - i == 0 || (i - index) % (matrixSize + 1) == 0 )
211 leftUnionArray[i] = rightUnionArray[count];
213 leftUnionArray[i].setFConst(0.0f);
217 if (node->getType().getObjectSize() > 1)
224 bool ParseLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it)
226 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
227 oit->infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
232 bool ParseBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it)
234 TConstTraverser* oit = static_cast<TConstTraverser*>(it);
235 oit->infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
241 // This function is the one to call externally to start the traversal.
242 // Individual functions can be initialized to 0 to skip processing of that
243 // type of node. It's children will still be processed.
245 bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, constUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
250 TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);
252 it.visitAggregate = ParseAggregate;
253 it.visitBinary = ParseBinary;
254 it.visitConstantUnion = ParseConstantUnion;
255 it.visitSelection = ParseSelection;
256 it.visitSymbol = ParseSymbol;
257 it.visitUnary = ParseUnary;
258 it.visitLoop = ParseLoop;
259 it.visitBranch = ParseBranch;