//POSSIBILITY OF SUCH DAMAGE.
//
-#include "ParseHelper.h"
-
//
-// Use this class to carry along data from node to node in
-// the traversal
+// Travarse a tree of constants to create a single folded constant.
+// It should only be used when the whole tree is known to be constant.
//
+
+#include "ParseHelper.h"
+
+namespace glslang {
+
class TConstTraverser : public TIntermTraverser {
public:
- TConstTraverser(constUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TType& t) : unionArray(cUnion), type(t),
- constructorType(constructType), singleConstantParam(singleConstParam), infoSink(sink), error(false), isMatrix(false),
- matrixCols(0), matrixRows(0) { index = 0; tOp = EOpNull;}
- int index ;
- constUnion *unionArray;
+ TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t)
+ : unionArray(cUnion), type(t),
+ constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false),
+ matrixCols(0), matrixRows(0) { index = 0; tOp = EOpNull; }
+
+ virtual void visitConstantUnion(TIntermConstantUnion* node);
+ virtual bool visitAggregate(TVisit, TIntermAggregate* node);
+
+ int index;
+ TConstUnionArray unionArray;
TOperator tOp;
- TType type;
+ const TType& type;
TOperator constructorType;
bool singleConstantParam;
- TInfoSink& infoSink;
bool error;
int size; // size of the constructor ( 4 for vec4)
bool isMatrix;
int matrixCols;
int matrixRows;
-};
-
-//
-// The rest of the file are the traversal functions. The last one
-// is the one that starts the traversal.
-//
-// Return true from interior nodes to have the external traversal
-// continue on to children. If you process children yourself,
-// return false.
-//
-
-void ParseSymbol(TIntermSymbol* node, TIntermTraverser* it)
-{
- TConstTraverser* oit = static_cast<TConstTraverser*>(it);
- oit->infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
- return;
-}
-
-bool ParseBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
-{
- TConstTraverser* oit = static_cast<TConstTraverser*>(it);
-
- TStorageQualifier qualifier = node->getType().getQualifier().storage;
-
- if (qualifier != EvqConst) {
- const int maxSize = 200;
- char buf[maxSize];
- snprintf(buf, maxSize, "'constructor' : assigning non-constant to %s", oit->type.getCompleteString().c_str());
- oit->infoSink.info.message(EPrefixError, buf, node->getLine());
- oit->error = true;
-
- return false;
- }
-
- oit->infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
-
- return false;
-}
-
-bool ParseUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
-{
- TConstTraverser* oit = static_cast<TConstTraverser*>(it);
-
- const int maxSize = 200;
- char buf[maxSize];
- snprintf(buf, maxSize, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
- oit->infoSink.info.message(EPrefixError, buf, node->getLine());
- oit->error = true;
-
- return false;
-}
+protected:
+ TConstTraverser(TConstTraverser&);
+ TConstTraverser& operator=(TConstTraverser&);
+};
-bool ParseAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
+bool TConstTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
{
- TConstTraverser* oit = static_cast<TConstTraverser*>(it);
-
- if (!node->isConstructor() && node->getOp() != EOpComma) {
- const int maxSize = 200;
- char buf[maxSize];
- snprintf(buf, maxSize, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
- oit->infoSink.info.message(EPrefixError, buf, node->getLine());
- oit->error = true;
+ if (! node->isConstructor() && node->getOp() != EOpComma) {
+ error = true;
return false;
}
if (node->getSequence().size() == 0) {
- oit->error = true;
+ error = true;
return false;
}
bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
if (flag) {
- oit->singleConstantParam = true;
- oit->constructorType = node->getOp();
- oit->size = node->getType().getObjectSize();
+ singleConstantParam = true;
+ constructorType = node->getOp();
+ size = node->getType().computeNumComponents();
if (node->getType().isMatrix()) {
- oit->isMatrix = true;
- oit->matrixCols = node->getType().getMatrixCols();
- oit->matrixRows = node->getType().getMatrixRows();
+ isMatrix = true;
+ matrixCols = node->getType().getMatrixCols();
+ matrixRows = node->getType().getMatrixRows();
}
}
p != node->getSequence().end(); p++) {
if (node->getOp() == EOpComma)
- oit->index = 0;
+ index = 0;
- (*p)->traverse(oit);
+ (*p)->traverse(this);
}
if (flag)
{
- oit->singleConstantParam = false;
- oit->constructorType = EOpNull;
- oit->size = 0;
- oit->isMatrix = false;
- oit->matrixCols = 0;
- oit->matrixRows = 0;
+ singleConstantParam = false;
+ constructorType = EOpNull;
+ size = 0;
+ isMatrix = false;
+ matrixCols = 0;
+ matrixRows = 0;
}
return false;
}
-bool ParseSelection(bool /* preVisit */, TIntermSelection* node, TIntermTraverser* it)
-{
- TConstTraverser* oit = static_cast<TConstTraverser*>(it);
- oit->infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
- oit->error = true;
- return false;
-}
-
-void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
+void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
{
- TConstTraverser* oit = static_cast<TConstTraverser*>(it);
- constUnion* leftUnionArray = oit->unionArray;
- int instanceSize = oit->type.getObjectSize();
+ TConstUnionArray leftUnionArray(unionArray);
+ int instanceSize = type.computeNumComponents();
- if (oit->index >= instanceSize)
+ if (index >= instanceSize)
return;
- if (!oit->singleConstantParam) {
- int size = node->getType().getObjectSize();
+ if (! singleConstantParam) {
+ int rightUnionSize = node->getType().computeNumComponents();
- constUnion *rightUnionArray = node->getUnionArrayPointer();
- for (int i=0; i < size; i++) {
- if (oit->index >= instanceSize)
+ const TConstUnionArray& rightUnionArray = node->getConstArray();
+ for (int i = 0; i < rightUnionSize; i++) {
+ if (index >= instanceSize)
return;
- leftUnionArray[oit->index] = rightUnionArray[i];
+ leftUnionArray[index] = rightUnionArray[i];
- (oit->index)++;
+ index++;
}
} else {
- int size, totalSize, matrixCols, matrixRows;
- bool isMatrix = false;
- size = oit->size;
- matrixCols = oit->matrixCols;
- matrixRows = oit->matrixRows;
- isMatrix = oit->isMatrix;
- totalSize = oit->index + size;
- constUnion *rightUnionArray = node->getUnionArrayPointer();
- if (!isMatrix) {
+ int endIndex = index + size;
+ const TConstUnionArray& rightUnionArray = node->getConstArray();
+ if (! isMatrix) {
int count = 0;
- for (int i = oit->index; i < totalSize; i++) {
+ int nodeComps = node->getType().computeNumComponents();
+ for (int i = index; i < endIndex; i++) {
if (i >= instanceSize)
return;
leftUnionArray[i] = rightUnionArray[count];
- (oit->index)++;
+ (index)++;
- if (node->getType().getObjectSize() > 1)
+ if (nodeComps > 1)
count++;
}
- } else { // for matrix constructors
- int count = 0;
- int index = oit->index;
- for (int i = index; i < totalSize; i++) {
- if (i >= instanceSize)
- return;
- if (index - i == 0 || (i - index) % (matrixRows + 1) == 0 )
- leftUnionArray[i] = rightUnionArray[count];
- else
- leftUnionArray[i].setFConst(0.0f);
-
- (oit->index)++;
-
- if (node->getType().getObjectSize() > 1)
- count++;
+ } else {
+ // constructing a matrix, but from what?
+ if (node->isMatrix()) {
+ // Matrix from a matrix; this has the outer matrix, node is the argument matrix.
+ // Traverse the outer, potentially bigger matrix, fill in missing pieces with the
+ // identity matrix.
+ for (int c = 0; c < matrixCols; ++c) {
+ for (int r = 0; r < matrixRows; ++r) {
+ int targetOffset = index + c * matrixRows + r;
+ if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) {
+ int srcOffset = c * node->getType().getMatrixRows() + r;
+ leftUnionArray[targetOffset] = rightUnionArray[srcOffset];
+ } else if (r == c)
+ leftUnionArray[targetOffset].setDConst(1.0);
+ else
+ leftUnionArray[targetOffset].setDConst(0.0);
+ }
+ }
+ } else {
+ // matrix from vector
+ int count = 0;
+ const int startIndex = index;
+ int nodeComps = node->getType().computeNumComponents();
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i >= instanceSize)
+ return;
+ if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
+ leftUnionArray[i] = rightUnionArray[count];
+ else
+ leftUnionArray[i].setDConst(0.0);
+
+ index++;
+
+ if (nodeComps > 1)
+ count++;
+ }
}
}
}
}
-bool ParseLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it)
-{
- TConstTraverser* oit = static_cast<TConstTraverser*>(it);
- oit->infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
- oit->error = true;
-
- return false;
-}
-
-bool ParseBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it)
-{
- TConstTraverser* oit = static_cast<TConstTraverser*>(it);
- oit->infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
- oit->error = true;
-
- return false;
-}
-
-//
-// This function is the one to call externally to start the traversal.
-// Individual functions can be initialized to 0 to skip processing of that
-// type of node. It's children will still be processed.
-//
-bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, constUnion* unionArray, TOperator constructorType, TType t, bool singleConstantParam)
+bool TIntermediate::parseConstTree(TIntermNode* root, TConstUnionArray unionArray, TOperator constructorType, const TType& t, bool singleConstantParam)
{
if (root == 0)
return false;
- TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, t);
+ TConstTraverser it(unionArray, singleConstantParam, constructorType, t);
- it.visitAggregate = ParseAggregate;
- it.visitBinary = ParseBinary;
- it.visitConstantUnion = ParseConstantUnion;
- it.visitSelection = ParseSelection;
- it.visitSymbol = ParseSymbol;
- it.visitUnary = ParseUnary;
- it.visitLoop = ParseLoop;
- it.visitBranch = ParseBranch;
-
root->traverse(&it);
if (it.error)
return true;
else
return false;
}
+
+} // end namespace glslang