summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/angle/src/compiler/translator/parseConst.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/angle/src/compiler/translator/parseConst.cpp')
-rw-r--r--chromium/third_party/angle/src/compiler/translator/parseConst.cpp251
1 files changed, 251 insertions, 0 deletions
diff --git a/chromium/third_party/angle/src/compiler/translator/parseConst.cpp b/chromium/third_party/angle/src/compiler/translator/parseConst.cpp
new file mode 100644
index 00000000000..33617e53d9a
--- /dev/null
+++ b/chromium/third_party/angle/src/compiler/translator/parseConst.cpp
@@ -0,0 +1,251 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/ParseContext.h"
+
+//
+// Use this class to carry along data from node to node in
+// the traversal
+//
+class TConstTraverser : public TIntermTraverser {
+public:
+ TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TType& t)
+ : error(false),
+ index(0),
+ unionArray(cUnion),
+ type(t),
+ constructorType(constructType),
+ singleConstantParam(singleConstParam),
+ infoSink(sink),
+ size(0),
+ isDiagonalMatrixInit(false),
+ matrixCols(0),
+ matrixRows(0) {
+ }
+
+ bool error;
+
+protected:
+ void visitSymbol(TIntermSymbol*);
+ void visitConstantUnion(TIntermConstantUnion*);
+ bool visitBinary(Visit visit, TIntermBinary*);
+ bool visitUnary(Visit visit, TIntermUnary*);
+ bool visitSelection(Visit visit, TIntermSelection*);
+ bool visitAggregate(Visit visit, TIntermAggregate*);
+ bool visitLoop(Visit visit, TIntermLoop*);
+ bool visitBranch(Visit visit, TIntermBranch*);
+
+ size_t index;
+ ConstantUnion *unionArray;
+ TType type;
+ TOperator constructorType;
+ bool singleConstantParam;
+ TInfoSink& infoSink;
+ size_t size; // size of the constructor ( 4 for vec4)
+ bool isDiagonalMatrixInit;
+ int matrixCols; // columns of the matrix
+ int matrixRows; // rows of the matrix
+};
+
+//
+// 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 TConstTraverser::visitSymbol(TIntermSymbol* node)
+{
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor");
+ return;
+
+}
+
+bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
+{
+ TQualifier qualifier = node->getType().getQualifier();
+
+ if (qualifier != EvqConst) {
+ TString buf;
+ buf.append("'constructor' : assigning non-constant to ");
+ buf.append(type.getCompleteString());
+ infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
+ error = true;
+ return false;
+ }
+
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor");
+
+ return false;
+}
+
+bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
+{
+ TString buf;
+ buf.append("'constructor' : assigning non-constant to ");
+ buf.append(type.getCompleteString());
+ infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
+ error = true;
+ return false;
+}
+
+bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+ if (!node->isConstructor() && node->getOp() != EOpComma) {
+ TString buf;
+ buf.append("'constructor' : assigning non-constant to ");
+ buf.append(type.getCompleteString());
+ infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
+ error = true;
+ return false;
+ }
+
+ if (node->getSequence().size() == 0) {
+ error = true;
+ return false;
+ }
+
+ bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
+ if (flag)
+ {
+ singleConstantParam = true;
+ constructorType = node->getOp();
+ size = node->getType().getObjectSize();
+
+ if (node->getType().isMatrix()) {
+ isDiagonalMatrixInit = true;
+ matrixCols = node->getType().getCols();
+ matrixRows = node->getType().getRows();
+ }
+ }
+
+ for (TIntermSequence::iterator p = node->getSequence().begin();
+ p != node->getSequence().end(); p++) {
+
+ if (node->getOp() == EOpComma)
+ index = 0;
+
+ (*p)->traverse(this);
+ }
+ if (flag)
+ {
+ singleConstantParam = false;
+ constructorType = EOpNull;
+ size = 0;
+ isDiagonalMatrixInit = false;
+ matrixCols = 0;
+ matrixRows = 0;
+ }
+ return false;
+}
+
+bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
+{
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor");
+ error = true;
+ return false;
+}
+
+void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+ if (!node->getUnionArrayPointer())
+ {
+ // The constant was not initialized, this should already have been logged
+ assert(infoSink.info.size() != 0);
+ return;
+ }
+
+ ConstantUnion* leftUnionArray = unionArray;
+ size_t instanceSize = type.getObjectSize();
+
+ if (index >= instanceSize)
+ return;
+
+ if (!singleConstantParam) {
+ size_t objectSize = node->getType().getObjectSize();
+
+ ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+ for (size_t i=0; i < objectSize; i++) {
+ if (index >= instanceSize)
+ return;
+ leftUnionArray[index] = rightUnionArray[i];
+
+ (index)++;
+ }
+ } else {
+ size_t totalSize = index + size;
+ ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+ if (!isDiagonalMatrixInit) {
+ int count = 0;
+ for (size_t i = index; i < totalSize; i++) {
+ if (i >= instanceSize)
+ return;
+
+ leftUnionArray[i] = rightUnionArray[count];
+
+ (index)++;
+
+ if (node->getType().getObjectSize() > 1)
+ count++;
+ }
+ }
+ else
+ {
+ // for matrix diagonal constructors from a single scalar
+ for (int i = 0, col = 0; col < matrixCols; col++)
+ {
+ for (int row = 0; row < matrixRows; row++, i++)
+ {
+ if (col == row)
+ {
+ leftUnionArray[i] = rightUnionArray[0];
+ }
+ else
+ {
+ leftUnionArray[i].setFConst(0.0f);
+ }
+
+ (index)++;
+ }
+ }
+ }
+ }
+}
+
+bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
+{
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor");
+ error = true;
+ return false;
+}
+
+bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
+{
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor");
+ 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(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TType t, bool singleConstantParam)
+{
+ if (root == 0)
+ return false;
+
+ TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, t);
+
+ root->traverse(&it);
+ if (it.error)
+ return true;
+ else
+ return false;
+}