2 // Copyright (c) 2002-2010 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.
7 #include "compiler/ParseHelper.h"
10 // Use this class to carry along data from node to node in
13 class TConstTraverser : public TIntermTraverser {
15 TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t)
20 constructorType(constructType),
21 singleConstantParam(singleConstParam),
23 symbolTable(symTable),
32 void visitSymbol(TIntermSymbol*);
33 void visitConstantUnion(TIntermConstantUnion*);
34 bool visitBinary(Visit visit, TIntermBinary*);
35 bool visitUnary(Visit visit, TIntermUnary*);
36 bool visitSelection(Visit visit, TIntermSelection*);
37 bool visitAggregate(Visit visit, TIntermAggregate*);
38 bool visitLoop(Visit visit, TIntermLoop*);
39 bool visitBranch(Visit visit, TIntermBranch*);
42 ConstantUnion *unionArray;
44 TOperator constructorType;
45 bool singleConstantParam;
47 TSymbolTable& symbolTable;
48 int size; // size of the constructor ( 4 for vec4)
50 int matrixSize; // dimension of the matrix (nominal size and not the instance size)
54 // The rest of the file are the traversal functions. The last one
55 // is the one that starts the traversal.
57 // Return true from interior nodes to have the external traversal
58 // continue on to children. If you process children yourself,
62 void TConstTraverser::visitSymbol(TIntermSymbol* node)
64 infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
69 bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
71 TQualifier qualifier = node->getType().getQualifier();
73 if (qualifier != EvqConst) {
75 buf.append("'constructor' : assigning non-constant to ");
76 buf.append(type.getCompleteString());
77 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
82 infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
87 bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
90 buf.append("'constructor' : assigning non-constant to ");
91 buf.append(type.getCompleteString());
92 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
97 bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
99 if (!node->isConstructor() && node->getOp() != EOpComma) {
101 buf.append("'constructor' : assigning non-constant to ");
102 buf.append(type.getCompleteString());
103 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
108 if (node->getSequence().size() == 0) {
113 bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
116 singleConstantParam = true;
117 constructorType = node->getOp();
118 size = node->getType().getObjectSize();
120 if (node->getType().isMatrix()) {
122 matrixSize = node->getType().getNominalSize();
126 for (TIntermSequence::iterator p = node->getSequence().begin();
127 p != node->getSequence().end(); p++) {
129 if (node->getOp() == EOpComma)
132 (*p)->traverse(this);
136 singleConstantParam = false;
137 constructorType = EOpNull;
145 bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
147 infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
152 void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
154 ConstantUnion* leftUnionArray = unionArray;
155 int instanceSize = type.getObjectSize();
157 if (index >= instanceSize)
160 if (!singleConstantParam) {
161 int size = node->getType().getObjectSize();
163 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
164 for (int i=0; i < size; i++) {
165 if (index >= instanceSize)
167 leftUnionArray[index] = rightUnionArray[i];
172 int totalSize = index + size;
173 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
176 for (int i = index; i < totalSize; i++) {
177 if (i >= instanceSize)
180 leftUnionArray[i] = rightUnionArray[count];
184 if (node->getType().getObjectSize() > 1)
187 } else { // for matrix constructors
190 for (int i = index; i < totalSize; i++) {
191 if (i >= instanceSize)
193 if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
194 leftUnionArray[i] = rightUnionArray[count];
196 leftUnionArray[i].setFConst(0.0f);
200 if (node->getType().getObjectSize() > 1)
207 bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
209 infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
214 bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
216 infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
222 // This function is the one to call externally to start the traversal.
223 // Individual functions can be initialized to 0 to skip processing of that
224 // type of node. It's children will still be processed.
226 bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
231 TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);