Rename compiler intermediate source files.
This prevents confusion between "TIntermediate" and "TIntermNode".
BUG=angle:711
Change-Id: Ib7a086382a479db3f77bf2ab06ce321aa7b35d13
Reviewed-on: https://chromium-review.googlesource.com/212936
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Reviewed-by: Nicolas Capens <capn@chromium.org>
diff --git a/src/compiler.gypi b/src/compiler.gypi
index ff180e7..dadc4ca 100644
--- a/src/compiler.gypi
+++ b/src/compiler.gypi
@@ -72,7 +72,10 @@
'compiler/translator/InitializeVariables.cpp',
'compiler/translator/InitializeVariables.h',
'compiler/translator/IntermTraverse.cpp',
+ 'compiler/translator/Intermediate.h',
'compiler/translator/Intermediate.cpp',
+ 'compiler/translator/IntermNode.h',
+ 'compiler/translator/IntermNode.cpp',
'compiler/translator/LoopInfo.cpp',
'compiler/translator/LoopInfo.h',
'compiler/translator/MMap.h',
@@ -151,7 +154,6 @@
'compiler/translator/intermOut.cpp',
'compiler/translator/intermediate.h',
'compiler/translator/length_limits.h',
- 'compiler/translator/localintermediate.h',
'compiler/translator/parseConst.cpp',
'compiler/translator/timing/RestrictFragmentShaderTiming.cpp',
'compiler/translator/timing/RestrictFragmentShaderTiming.h',
diff --git a/src/compiler/translator/BuiltInFunctionEmulator.h b/src/compiler/translator/BuiltInFunctionEmulator.h
index 926b6be..c6bf77c 100644
--- a/src/compiler/translator/BuiltInFunctionEmulator.h
+++ b/src/compiler/translator/BuiltInFunctionEmulator.h
@@ -8,7 +8,7 @@
#define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
//
// This class decides which built-in functions need to be replaced with the
diff --git a/src/compiler/translator/DetectCallDepth.h b/src/compiler/translator/DetectCallDepth.h
index cb76f1d..8681065 100644
--- a/src/compiler/translator/DetectCallDepth.h
+++ b/src/compiler/translator/DetectCallDepth.h
@@ -8,7 +8,7 @@
#define COMPILER_DETECT_RECURSION_H_
#include <limits.h>
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
#include "compiler/translator/VariableInfo.h"
class TInfoSink;
diff --git a/src/compiler/translator/DetectDiscontinuity.h b/src/compiler/translator/DetectDiscontinuity.h
index 1dd8be9..35d66cb 100644
--- a/src/compiler/translator/DetectDiscontinuity.h
+++ b/src/compiler/translator/DetectDiscontinuity.h
@@ -11,7 +11,7 @@
#ifndef COMPILER_DETECTDISCONTINUITY_H_
#define COMPILER_DETECTDISCONTINUITY_H_
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
namespace sh
{
diff --git a/src/compiler/translator/FlagStd140Structs.h b/src/compiler/translator/FlagStd140Structs.h
index 610205e..c93a6f8 100644
--- a/src/compiler/translator/FlagStd140Structs.h
+++ b/src/compiler/translator/FlagStd140Structs.h
@@ -7,7 +7,7 @@
#ifndef COMPILER_FLAGSTD140STRUCTS_H_
#define COMPILER_FLAGSTD140STRUCTS_H_
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
namespace sh
{
diff --git a/src/compiler/translator/HashNames.h b/src/compiler/translator/HashNames.h
index 8516142..26546a3 100644
--- a/src/compiler/translator/HashNames.h
+++ b/src/compiler/translator/HashNames.h
@@ -9,7 +9,7 @@
#include <map>
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
#define HASHED_NAME_PREFIX "webgl_"
diff --git a/src/compiler/translator/Initialize.cpp b/src/compiler/translator/Initialize.cpp
index e91d64f..10b21e6 100644
--- a/src/compiler/translator/Initialize.cpp
+++ b/src/compiler/translator/Initialize.cpp
@@ -12,7 +12,7 @@
#include "compiler/translator/Initialize.h"
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
#include "angle_gl.h"
void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable)
diff --git a/src/compiler/translator/InitializeVariables.h b/src/compiler/translator/InitializeVariables.h
index 81ab9fe..59c3ea0 100644
--- a/src/compiler/translator/InitializeVariables.h
+++ b/src/compiler/translator/InitializeVariables.h
@@ -7,7 +7,7 @@
#ifndef COMPILER_INITIALIZE_VARIABLES_H_
#define COMPILER_INITIALIZE_VARIABLES_H_
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
class InitializeVariables : public TIntermTraverser
{
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
new file mode 100644
index 0000000..b155545
--- /dev/null
+++ b/src/compiler/translator/IntermNode.cpp
@@ -0,0 +1,1107 @@
+//
+// Copyright (c) 2002-2014 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.
+//
+
+//
+// Build the intermediate representation.
+//
+
+#include <float.h>
+#include <limits.h>
+#include <algorithm>
+
+#include "compiler/translator/HashNames.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace
+{
+
+TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
+{
+ return left > right ? left : right;
+}
+
+bool ValidateMultiplication(TOperator op, const TType &left, const TType &right)
+{
+ switch (op)
+ {
+ case EOpMul:
+ case EOpMulAssign:
+ return left.getNominalSize() == right.getNominalSize() &&
+ left.getSecondarySize() == right.getSecondarySize();
+ case EOpVectorTimesScalar:
+ case EOpVectorTimesScalarAssign:
+ return true;
+ case EOpVectorTimesMatrix:
+ return left.getNominalSize() == right.getRows();
+ case EOpVectorTimesMatrixAssign:
+ return left.getNominalSize() == right.getRows() &&
+ left.getNominalSize() == right.getCols();
+ case EOpMatrixTimesVector:
+ return left.getCols() == right.getNominalSize();
+ case EOpMatrixTimesScalar:
+ case EOpMatrixTimesScalarAssign:
+ return true;
+ case EOpMatrixTimesMatrix:
+ return left.getCols() == right.getRows();
+ case EOpMatrixTimesMatrixAssign:
+ return left.getCols() == right.getCols() &&
+ left.getRows() == right.getRows();
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool CompareStructure(const TType& leftNodeType,
+ ConstantUnion *rightUnionArray,
+ ConstantUnion *leftUnionArray);
+
+bool CompareStruct(const TType &leftNodeType,
+ ConstantUnion *rightUnionArray,
+ ConstantUnion *leftUnionArray)
+{
+ const TFieldList &fields = leftNodeType.getStruct()->fields();
+
+ size_t structSize = fields.size();
+ size_t index = 0;
+
+ for (size_t j = 0; j < structSize; j++)
+ {
+ size_t size = fields[j]->type()->getObjectSize();
+ for (size_t i = 0; i < size; i++)
+ {
+ if (fields[j]->type()->getBasicType() == EbtStruct)
+ {
+ if (!CompareStructure(*fields[j]->type(),
+ &rightUnionArray[index],
+ &leftUnionArray[index]))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (leftUnionArray[index] != rightUnionArray[index])
+ return false;
+ index++;
+ }
+ }
+ }
+ return true;
+}
+
+bool CompareStructure(const TType &leftNodeType,
+ ConstantUnion *rightUnionArray,
+ ConstantUnion *leftUnionArray)
+{
+ if (leftNodeType.isArray())
+ {
+ TType typeWithoutArrayness = leftNodeType;
+ typeWithoutArrayness.clearArrayness();
+
+ size_t arraySize = leftNodeType.getArraySize();
+
+ for (size_t i = 0; i < arraySize; ++i)
+ {
+ size_t offset = typeWithoutArrayness.getObjectSize() * i;
+ if (!CompareStruct(typeWithoutArrayness,
+ &rightUnionArray[offset],
+ &leftUnionArray[offset]))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
+ }
+ return true;
+}
+
+} // namespace anonymous
+
+
+////////////////////////////////////////////////////////////////
+//
+// Member functions of the nodes used for building the tree.
+//
+////////////////////////////////////////////////////////////////
+
+#define REPLACE_IF_IS(node, type, original, replacement) \
+ if (node == original) { \
+ node = static_cast<type *>(replacement); \
+ return true; \
+ }
+
+bool TIntermLoop::replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement)
+{
+ REPLACE_IF_IS(mInit, TIntermNode, original, replacement);
+ REPLACE_IF_IS(mCond, TIntermTyped, original, replacement);
+ REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement);
+ REPLACE_IF_IS(mBody, TIntermNode, original, replacement);
+ return false;
+}
+
+void TIntermLoop::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
+{
+ if (mInit)
+ {
+ nodeQueue->push(mInit);
+ }
+ if (mCond)
+ {
+ nodeQueue->push(mCond);
+ }
+ if (mExpr)
+ {
+ nodeQueue->push(mExpr);
+ }
+ if (mBody)
+ {
+ nodeQueue->push(mBody);
+ }
+}
+
+bool TIntermBranch::replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement)
+{
+ REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement);
+ return false;
+}
+
+void TIntermBranch::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
+{
+ if (mExpression)
+ {
+ nodeQueue->push(mExpression);
+ }
+}
+
+bool TIntermBinary::replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement)
+{
+ REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement);
+ REPLACE_IF_IS(mRight, TIntermTyped, original, replacement);
+ return false;
+}
+
+void TIntermBinary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
+{
+ if (mLeft)
+ {
+ nodeQueue->push(mLeft);
+ }
+ if (mRight)
+ {
+ nodeQueue->push(mRight);
+ }
+}
+
+bool TIntermUnary::replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement)
+{
+ REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
+ return false;
+}
+
+void TIntermUnary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
+{
+ if (mOperand)
+ {
+ nodeQueue->push(mOperand);
+ }
+}
+
+bool TIntermAggregate::replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement)
+{
+ for (size_t ii = 0; ii < mSequence.size(); ++ii)
+ {
+ REPLACE_IF_IS(mSequence[ii], TIntermNode, original, replacement);
+ }
+ return false;
+}
+
+void TIntermAggregate::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
+{
+ for (size_t childIndex = 0; childIndex < mSequence.size(); childIndex++)
+ {
+ nodeQueue->push(mSequence[childIndex]);
+ }
+}
+
+bool TIntermSelection::replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement)
+{
+ REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
+ REPLACE_IF_IS(mTrueBlock, TIntermNode, original, replacement);
+ REPLACE_IF_IS(mFalseBlock, TIntermNode, original, replacement);
+ return false;
+}
+
+void TIntermSelection::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
+{
+ if (mCondition)
+ {
+ nodeQueue->push(mCondition);
+ }
+ if (mTrueBlock)
+ {
+ nodeQueue->push(mTrueBlock);
+ }
+ if (mFalseBlock)
+ {
+ nodeQueue->push(mFalseBlock);
+ }
+}
+
+//
+// Say whether or not an operation node changes the value of a variable.
+//
+bool TIntermOperator::isAssignment() const
+{
+ switch (mOp)
+ {
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ case EOpAssign:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpMulAssign:
+ case EOpVectorTimesMatrixAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpMatrixTimesMatrixAssign:
+ case EOpDivAssign:
+ return true;
+ default:
+ return false;
+ }
+}
+
+//
+// returns true if the operator is for one of the constructors
+//
+bool TIntermOperator::isConstructor() const
+{
+ switch (mOp)
+ {
+ case EOpConstructVec2:
+ case EOpConstructVec3:
+ case EOpConstructVec4:
+ case EOpConstructMat2:
+ case EOpConstructMat3:
+ case EOpConstructMat4:
+ case EOpConstructFloat:
+ case EOpConstructIVec2:
+ case EOpConstructIVec3:
+ case EOpConstructIVec4:
+ case EOpConstructInt:
+ case EOpConstructUVec2:
+ case EOpConstructUVec3:
+ case EOpConstructUVec4:
+ case EOpConstructUInt:
+ case EOpConstructBVec2:
+ case EOpConstructBVec3:
+ case EOpConstructBVec4:
+ case EOpConstructBool:
+ case EOpConstructStruct:
+ return true;
+ default:
+ return false;
+ }
+}
+
+//
+// Make sure the type of a unary operator is appropriate for its
+// combination of operation and operand type.
+//
+// Returns false in nothing makes sense.
+//
+bool TIntermUnary::promote(TInfoSink &)
+{
+ switch (mOp)
+ {
+ case EOpLogicalNot:
+ if (mOperand->getBasicType() != EbtBool)
+ return false;
+ break;
+ case EOpNegative:
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ if (mOperand->getBasicType() == EbtBool)
+ return false;
+ break;
+
+ // operators for built-ins are already type checked against their prototype
+ case EOpAny:
+ case EOpAll:
+ case EOpVectorLogicalNot:
+ return true;
+
+ default:
+ if (mOperand->getBasicType() != EbtFloat)
+ return false;
+ }
+
+ setType(mOperand->getType());
+ mType.setQualifier(EvqTemporary);
+
+ return true;
+}
+
+//
+// Establishes the type of the resultant operation, as well as
+// makes the operator the correct one for the operands.
+//
+// Returns false if operator can't work on operands.
+//
+bool TIntermBinary::promote(TInfoSink &infoSink)
+{
+ // This function only handles scalars, vectors, and matrices.
+ if (mLeft->isArray() || mRight->isArray())
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(),
+ "Invalid operation for arrays");
+ return false;
+ }
+
+ // GLSL ES 2.0 does not support implicit type casting.
+ // So the basic type should always match.
+ if (mLeft->getBasicType() != mRight->getBasicType())
+ {
+ return false;
+ }
+
+ //
+ // Base assumption: just make the type the same as the left
+ // operand. Then only deviations from this need be coded.
+ //
+ setType(mLeft->getType());
+
+ // The result gets promoted to the highest precision.
+ TPrecision higherPrecision = GetHigherPrecision(
+ mLeft->getPrecision(), mRight->getPrecision());
+ getTypePointer()->setPrecision(higherPrecision);
+
+ // Binary operations results in temporary variables unless both
+ // operands are const.
+ if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst)
+ {
+ getTypePointer()->setQualifier(EvqTemporary);
+ }
+
+ const int nominalSize =
+ std::max(mLeft->getNominalSize(), mRight->getNominalSize());
+
+ //
+ // All scalars or structs. Code after this test assumes this case is removed!
+ //
+ if (nominalSize == 1)
+ {
+ switch (mOp)
+ {
+ //
+ // Promote to conditional
+ //
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ setType(TType(EbtBool, EbpUndefined));
+ break;
+
+ //
+ // And and Or operate on conditionals
+ //
+ case EOpLogicalAnd:
+ case EOpLogicalOr:
+ // Both operands must be of type bool.
+ if (mLeft->getBasicType() != EbtBool || mRight->getBasicType() != EbtBool)
+ {
+ return false;
+ }
+ setType(TType(EbtBool, EbpUndefined));
+ break;
+
+ default:
+ break;
+ }
+ return true;
+ }
+
+ // If we reach here, at least one of the operands is vector or matrix.
+ // The other operand could be a scalar, vector, or matrix.
+ // Can these two operands be combined?
+ //
+ TBasicType basicType = mLeft->getBasicType();
+ switch (mOp)
+ {
+ case EOpMul:
+ if (!mLeft->isMatrix() && mRight->isMatrix())
+ {
+ if (mLeft->isVector())
+ {
+ mOp = EOpVectorTimesMatrix;
+ setType(TType(basicType, higherPrecision, EvqTemporary,
+ mRight->getCols(), 1));
+ }
+ else
+ {
+ mOp = EOpMatrixTimesScalar;
+ setType(TType(basicType, higherPrecision, EvqTemporary,
+ mRight->getCols(), mRight->getRows()));
+ }
+ }
+ else if (mLeft->isMatrix() && !mRight->isMatrix())
+ {
+ if (mRight->isVector())
+ {
+ mOp = EOpMatrixTimesVector;
+ setType(TType(basicType, higherPrecision, EvqTemporary,
+ mLeft->getRows(), 1));
+ }
+ else
+ {
+ mOp = EOpMatrixTimesScalar;
+ }
+ }
+ else if (mLeft->isMatrix() && mRight->isMatrix())
+ {
+ mOp = EOpMatrixTimesMatrix;
+ setType(TType(basicType, higherPrecision, EvqTemporary,
+ mRight->getCols(), mLeft->getRows()));
+ }
+ else if (!mLeft->isMatrix() && !mRight->isMatrix())
+ {
+ if (mLeft->isVector() && mRight->isVector())
+ {
+ // leave as component product
+ }
+ else if (mLeft->isVector() || mRight->isVector())
+ {
+ mOp = EOpVectorTimesScalar;
+ setType(TType(basicType, higherPrecision, EvqTemporary,
+ nominalSize, 1));
+ }
+ }
+ else
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(),
+ "Missing elses");
+ return false;
+ }
+
+ if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType()))
+ {
+ return false;
+ }
+ break;
+
+ case EOpMulAssign:
+ if (!mLeft->isMatrix() && mRight->isMatrix())
+ {
+ if (mLeft->isVector())
+ {
+ mOp = EOpVectorTimesMatrixAssign;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (mLeft->isMatrix() && !mRight->isMatrix())
+ {
+ if (mRight->isVector())
+ {
+ return false;
+ }
+ else
+ {
+ mOp = EOpMatrixTimesScalarAssign;
+ }
+ }
+ else if (mLeft->isMatrix() && mRight->isMatrix())
+ {
+ mOp = EOpMatrixTimesMatrixAssign;
+ setType(TType(basicType, higherPrecision, EvqTemporary,
+ mRight->getCols(), mLeft->getRows()));
+ }
+ else if (!mLeft->isMatrix() && !mRight->isMatrix())
+ {
+ if (mLeft->isVector() && mRight->isVector())
+ {
+ // leave as component product
+ }
+ else if (mLeft->isVector() || mRight->isVector())
+ {
+ if (!mLeft->isVector())
+ return false;
+ mOp = EOpVectorTimesScalarAssign;
+ setType(TType(basicType, higherPrecision, EvqTemporary,
+ mLeft->getNominalSize(), 1));
+ }
+ }
+ else
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(),
+ "Missing elses");
+ return false;
+ }
+
+ if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType()))
+ {
+ return false;
+ }
+ break;
+
+ case EOpAssign:
+ case EOpInitialize:
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpDivAssign:
+ if ((mLeft->isMatrix() && mRight->isVector()) ||
+ (mLeft->isVector() && mRight->isMatrix()))
+ {
+ return false;
+ }
+
+ // Are the sizes compatible?
+ if (mLeft->getNominalSize() != mRight->getNominalSize() ||
+ mLeft->getSecondarySize() != mRight->getSecondarySize())
+ {
+ // If the nominal size of operands do not match:
+ // One of them must be scalar.
+ if (!mLeft->isScalar() && !mRight->isScalar())
+ return false;
+
+ // Operator cannot be of type pure assignment.
+ if (mOp == EOpAssign || mOp == EOpInitialize)
+ return false;
+ }
+
+ {
+ const int secondarySize = std::max(
+ mLeft->getSecondarySize(), mRight->getSecondarySize());
+ setType(TType(basicType, higherPrecision, EvqTemporary,
+ nominalSize, secondarySize));
+ }
+ break;
+
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ if ((mLeft->getNominalSize() != mRight->getNominalSize()) ||
+ (mLeft->getSecondarySize() != mRight->getSecondarySize()))
+ {
+ return false;
+ }
+ setType(TType(EbtBool, EbpUndefined));
+ break;
+
+ default:
+ return false;
+ }
+ return true;
+}
+
+//
+// The fold functions see if an operation on a constant can be done in place,
+// without generating run-time code.
+//
+// Returns the node to keep using, which may or may not be the node passed in.
+//
+TIntermTyped *TIntermConstantUnion::fold(
+ TOperator op, TIntermTyped *constantNode, TInfoSink &infoSink)
+{
+ ConstantUnion *unionArray = getUnionArrayPointer();
+
+ if (!unionArray)
+ return NULL;
+
+ size_t objectSize = getType().getObjectSize();
+
+ if (constantNode)
+ {
+ // binary operations
+ TIntermConstantUnion *node = constantNode->getAsConstantUnion();
+ ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+ TType returnType = getType();
+
+ if (!rightUnionArray)
+ return NULL;
+
+ // for a case like float f = 1.2 + vec4(2,3,4,5);
+ if (constantNode->getType().getObjectSize() == 1 && objectSize > 1)
+ {
+ rightUnionArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; ++i)
+ {
+ rightUnionArray[i] = *node->getUnionArrayPointer();
+ }
+ returnType = getType();
+ }
+ else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1)
+ {
+ // for a case like float f = vec4(2,3,4,5) + 1.2;
+ unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
+ for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
+ {
+ unionArray[i] = *getUnionArrayPointer();
+ }
+ returnType = node->getType();
+ objectSize = constantNode->getType().getObjectSize();
+ }
+
+ ConstantUnion *tempConstArray = NULL;
+ TIntermConstantUnion *tempNode;
+
+ bool boolNodeFlag = false;
+ switch(op)
+ {
+ case EOpAdd:
+ tempConstArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ tempConstArray[i] = unionArray[i] + rightUnionArray[i];
+ break;
+ case EOpSub:
+ tempConstArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ tempConstArray[i] = unionArray[i] - rightUnionArray[i];
+ break;
+
+ case EOpMul:
+ case EOpVectorTimesScalar:
+ case EOpMatrixTimesScalar:
+ tempConstArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ tempConstArray[i] = unionArray[i] * rightUnionArray[i];
+ break;
+
+ case EOpMatrixTimesMatrix:
+ {
+ if (getType().getBasicType() != EbtFloat ||
+ node->getBasicType() != EbtFloat)
+ {
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Constant Folding cannot be done for matrix multiply");
+ return NULL;
+ }
+
+ const int leftCols = getCols();
+ const int leftRows = getRows();
+ const int rightCols = constantNode->getType().getCols();
+ const int rightRows = constantNode->getType().getRows();
+ const int resultCols = rightCols;
+ const int resultRows = leftRows;
+
+ tempConstArray = new ConstantUnion[resultCols*resultRows];
+ for (int row = 0; row < resultRows; row++)
+ {
+ for (int column = 0; column < resultCols; column++)
+ {
+ tempConstArray[resultRows * column + row].setFConst(0.0f);
+ for (int i = 0; i < leftCols; i++)
+ {
+ tempConstArray[resultRows * column + row].setFConst(
+ tempConstArray[resultRows * column + row].getFConst() +
+ unionArray[i * leftRows + row].getFConst() *
+ rightUnionArray[column * rightRows + i].getFConst());
+ }
+ }
+ }
+
+ // update return type for matrix product
+ returnType.setPrimarySize(resultCols);
+ returnType.setSecondarySize(resultRows);
+ }
+ break;
+
+ case EOpDiv:
+ {
+ tempConstArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ {
+ switch (getType().getBasicType())
+ {
+ case EbtFloat:
+ if (rightUnionArray[i] == 0.0f)
+ {
+ infoSink.info.message(
+ EPrefixWarning, getLine(),
+ "Divide by zero error during constant folding");
+ tempConstArray[i].setFConst(
+ unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
+ }
+ else
+ {
+ tempConstArray[i].setFConst(
+ unionArray[i].getFConst() /
+ rightUnionArray[i].getFConst());
+ }
+ break;
+
+ case EbtInt:
+ if (rightUnionArray[i] == 0)
+ {
+ infoSink.info.message(
+ EPrefixWarning, getLine(),
+ "Divide by zero error during constant folding");
+ tempConstArray[i].setIConst(INT_MAX);
+ }
+ else
+ {
+ tempConstArray[i].setIConst(
+ unionArray[i].getIConst() /
+ rightUnionArray[i].getIConst());
+ }
+ break;
+
+ case EbtUInt:
+ if (rightUnionArray[i] == 0)
+ {
+ infoSink.info.message(
+ EPrefixWarning, getLine(),
+ "Divide by zero error during constant folding");
+ tempConstArray[i].setUConst(UINT_MAX);
+ }
+ else
+ {
+ tempConstArray[i].setUConst(
+ unionArray[i].getUConst() /
+ rightUnionArray[i].getUConst());
+ }
+ break;
+
+ default:
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Constant folding cannot be done for \"/\"");
+ return NULL;
+ }
+ }
+ }
+ break;
+
+ case EOpMatrixTimesVector:
+ {
+ if (node->getBasicType() != EbtFloat)
+ {
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Constant Folding cannot be done for matrix times vector");
+ return NULL;
+ }
+
+ const int matrixCols = getCols();
+ const int matrixRows = getRows();
+
+ tempConstArray = new ConstantUnion[matrixRows];
+
+ for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
+ {
+ tempConstArray[matrixRow].setFConst(0.0f);
+ for (int col = 0; col < matrixCols; col++)
+ {
+ tempConstArray[matrixRow].setFConst(
+ tempConstArray[matrixRow].getFConst() +
+ unionArray[col * matrixRows + matrixRow].getFConst() *
+ rightUnionArray[col].getFConst());
+ }
+ }
+
+ returnType = node->getType();
+ returnType.setPrimarySize(matrixRows);
+
+ tempNode = new TIntermConstantUnion(tempConstArray, returnType);
+ tempNode->setLine(getLine());
+
+ return tempNode;
+ }
+
+ case EOpVectorTimesMatrix:
+ {
+ if (getType().getBasicType() != EbtFloat)
+ {
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Constant Folding cannot be done for vector times matrix");
+ return NULL;
+ }
+
+ const int matrixCols = constantNode->getType().getCols();
+ const int matrixRows = constantNode->getType().getRows();
+
+ tempConstArray = new ConstantUnion[matrixCols];
+
+ for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++)
+ {
+ tempConstArray[matrixCol].setFConst(0.0f);
+ for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
+ {
+ tempConstArray[matrixCol].setFConst(
+ tempConstArray[matrixCol].getFConst() +
+ unionArray[matrixRow].getFConst() *
+ rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst());
+ }
+ }
+
+ returnType.setPrimarySize(matrixCols);
+ }
+ break;
+
+ case EOpLogicalAnd:
+ // this code is written for possible future use,
+ // will not get executed currently
+ {
+ tempConstArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ {
+ tempConstArray[i] = unionArray[i] && rightUnionArray[i];
+ }
+ }
+ break;
+
+ case EOpLogicalOr:
+ // this code is written for possible future use,
+ // will not get executed currently
+ {
+ tempConstArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ {
+ tempConstArray[i] = unionArray[i] || rightUnionArray[i];
+ }
+ }
+ break;
+
+ case EOpLogicalXor:
+ {
+ tempConstArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ {
+ switch (getType().getBasicType())
+ {
+ case EbtBool:
+ tempConstArray[i].setBConst(
+ unionArray[i] == rightUnionArray[i] ? false : true);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ }
+ break;
+
+ case EOpLessThan:
+ ASSERT(objectSize == 1);
+ tempConstArray = new ConstantUnion[1];
+ tempConstArray->setBConst(*unionArray < *rightUnionArray);
+ returnType = TType(EbtBool, EbpUndefined, EvqConst);
+ break;
+
+ case EOpGreaterThan:
+ ASSERT(objectSize == 1);
+ tempConstArray = new ConstantUnion[1];
+ tempConstArray->setBConst(*unionArray > *rightUnionArray);
+ returnType = TType(EbtBool, EbpUndefined, EvqConst);
+ break;
+
+ case EOpLessThanEqual:
+ {
+ ASSERT(objectSize == 1);
+ ConstantUnion constant;
+ constant.setBConst(*unionArray > *rightUnionArray);
+ tempConstArray = new ConstantUnion[1];
+ tempConstArray->setBConst(!constant.getBConst());
+ returnType = TType(EbtBool, EbpUndefined, EvqConst);
+ break;
+ }
+
+ case EOpGreaterThanEqual:
+ {
+ ASSERT(objectSize == 1);
+ ConstantUnion constant;
+ constant.setBConst(*unionArray < *rightUnionArray);
+ tempConstArray = new ConstantUnion[1];
+ tempConstArray->setBConst(!constant.getBConst());
+ returnType = TType(EbtBool, EbpUndefined, EvqConst);
+ break;
+ }
+
+ case EOpEqual:
+ if (getType().getBasicType() == EbtStruct)
+ {
+ if (!CompareStructure(node->getType(),
+ node->getUnionArrayPointer(),
+ unionArray))
+ {
+ boolNodeFlag = true;
+ }
+ }
+ else
+ {
+ for (size_t i = 0; i < objectSize; i++)
+ {
+ if (unionArray[i] != rightUnionArray[i])
+ {
+ boolNodeFlag = true;
+ break; // break out of for loop
+ }
+ }
+ }
+
+ tempConstArray = new ConstantUnion[1];
+ if (!boolNodeFlag)
+ {
+ tempConstArray->setBConst(true);
+ }
+ else
+ {
+ tempConstArray->setBConst(false);
+ }
+
+ tempNode = new TIntermConstantUnion(
+ tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
+ tempNode->setLine(getLine());
+
+ return tempNode;
+
+ case EOpNotEqual:
+ if (getType().getBasicType() == EbtStruct)
+ {
+ if (CompareStructure(node->getType(),
+ node->getUnionArrayPointer(),
+ unionArray))
+ {
+ boolNodeFlag = true;
+ }
+ }
+ else
+ {
+ for (size_t i = 0; i < objectSize; i++)
+ {
+ if (unionArray[i] == rightUnionArray[i])
+ {
+ boolNodeFlag = true;
+ break; // break out of for loop
+ }
+ }
+ }
+
+ tempConstArray = new ConstantUnion[1];
+ if (!boolNodeFlag)
+ {
+ tempConstArray->setBConst(true);
+ }
+ else
+ {
+ tempConstArray->setBConst(false);
+ }
+
+ tempNode = new TIntermConstantUnion(
+ tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
+ tempNode->setLine(getLine());
+
+ return tempNode;
+
+ default:
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Invalid operator for constant folding");
+ return NULL;
+ }
+ tempNode = new TIntermConstantUnion(tempConstArray, returnType);
+ tempNode->setLine(getLine());
+
+ return tempNode;
+ }
+ else
+ {
+ //
+ // Do unary operations
+ //
+ TIntermConstantUnion *newNode = 0;
+ ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ {
+ switch(op)
+ {
+ case EOpNegative:
+ switch (getType().getBasicType())
+ {
+ case EbtFloat:
+ tempConstArray[i].setFConst(-unionArray[i].getFConst());
+ break;
+ case EbtInt:
+ tempConstArray[i].setIConst(-unionArray[i].getIConst());
+ break;
+ case EbtUInt:
+ tempConstArray[i].setUConst(static_cast<unsigned int>(
+ -static_cast<int>(unionArray[i].getUConst())));
+ break;
+ default:
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return NULL;
+ }
+ break;
+
+ case EOpLogicalNot:
+ // this code is written for possible future use,
+ // will not get executed currently
+ switch (getType().getBasicType())
+ {
+ case EbtBool:
+ tempConstArray[i].setBConst(!unionArray[i].getBConst());
+ break;
+ default:
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return NULL;
+ }
+ break;
+
+ default:
+ return NULL;
+ }
+ }
+ newNode = new TIntermConstantUnion(tempConstArray, getType());
+ newNode->setLine(getLine());
+ return newNode;
+ }
+}
+
+// static
+TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction)
+{
+ if (hashFunction == NULL || name.empty())
+ return name;
+ khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
+ TStringStream stream;
+ stream << HASHED_NAME_PREFIX << std::hex << number;
+ TString hashedName = stream.str();
+ return hashedName;
+}
diff --git a/src/compiler/translator/IntermNode.h b/src/compiler/translator/IntermNode.h
new file mode 100644
index 0000000..892f284
--- /dev/null
+++ b/src/compiler/translator/IntermNode.h
@@ -0,0 +1,771 @@
+//
+// Copyright (c) 2002-2014 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.
+//
+
+//
+// Definition of the in-memory high-level intermediate representation
+// of shaders. This is a tree that parser creates.
+//
+// Nodes in the tree are defined as a hierarchy of classes derived from
+// TIntermNode. Each is a node in a tree. There is no preset branching factor;
+// each node can have it's own type of list of children.
+//
+
+#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_
+#define COMPILER_TRANSLATOR_INTERMEDIATE_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include <algorithm>
+#include <queue>
+
+#include "compiler/translator/Common.h"
+#include "compiler/translator/Types.h"
+#include "compiler/translator/ConstantUnion.h"
+
+//
+// Operators used by the high-level (parse tree) representation.
+//
+enum TOperator
+{
+ EOpNull, // if in a node, should only mean a node is still being built
+ EOpSequence, // denotes a list of statements, or parameters, etc.
+ EOpFunctionCall,
+ EOpFunction, // For function definition
+ EOpParameters, // an aggregate listing the parameters to a function
+
+ EOpDeclaration,
+ EOpPrototype,
+
+ //
+ // Unary operators
+ //
+
+ EOpNegative,
+ EOpLogicalNot,
+ EOpVectorLogicalNot,
+
+ EOpPostIncrement,
+ EOpPostDecrement,
+ EOpPreIncrement,
+ EOpPreDecrement,
+
+ //
+ // binary operations
+ //
+
+ EOpAdd,
+ EOpSub,
+ EOpMul,
+ EOpDiv,
+ EOpEqual,
+ EOpNotEqual,
+ EOpVectorEqual,
+ EOpVectorNotEqual,
+ EOpLessThan,
+ EOpGreaterThan,
+ EOpLessThanEqual,
+ EOpGreaterThanEqual,
+ EOpComma,
+
+ EOpVectorTimesScalar,
+ EOpVectorTimesMatrix,
+ EOpMatrixTimesVector,
+ EOpMatrixTimesScalar,
+
+ EOpLogicalOr,
+ EOpLogicalXor,
+ EOpLogicalAnd,
+
+ EOpIndexDirect,
+ EOpIndexIndirect,
+ EOpIndexDirectStruct,
+ EOpIndexDirectInterfaceBlock,
+
+ EOpVectorSwizzle,
+
+ //
+ // Built-in functions potentially mapped to operators
+ //
+
+ EOpRadians,
+ EOpDegrees,
+ EOpSin,
+ EOpCos,
+ EOpTan,
+ EOpAsin,
+ EOpAcos,
+ EOpAtan,
+
+ EOpPow,
+ EOpExp,
+ EOpLog,
+ EOpExp2,
+ EOpLog2,
+ EOpSqrt,
+ EOpInverseSqrt,
+
+ EOpAbs,
+ EOpSign,
+ EOpFloor,
+ EOpCeil,
+ EOpFract,
+ EOpMod,
+ EOpMin,
+ EOpMax,
+ EOpClamp,
+ EOpMix,
+ EOpStep,
+ EOpSmoothStep,
+
+ EOpLength,
+ EOpDistance,
+ EOpDot,
+ EOpCross,
+ EOpNormalize,
+ EOpFaceForward,
+ EOpReflect,
+ EOpRefract,
+
+ EOpDFdx, // Fragment only, OES_standard_derivatives extension
+ EOpDFdy, // Fragment only, OES_standard_derivatives extension
+ EOpFwidth, // Fragment only, OES_standard_derivatives extension
+
+ EOpMatrixTimesMatrix,
+
+ EOpAny,
+ EOpAll,
+
+ //
+ // Branch
+ //
+
+ EOpKill, // Fragment only
+ EOpReturn,
+ EOpBreak,
+ EOpContinue,
+
+ //
+ // Constructors
+ //
+
+ EOpConstructInt,
+ EOpConstructUInt,
+ EOpConstructBool,
+ EOpConstructFloat,
+ EOpConstructVec2,
+ EOpConstructVec3,
+ EOpConstructVec4,
+ EOpConstructBVec2,
+ EOpConstructBVec3,
+ EOpConstructBVec4,
+ EOpConstructIVec2,
+ EOpConstructIVec3,
+ EOpConstructIVec4,
+ EOpConstructUVec2,
+ EOpConstructUVec3,
+ EOpConstructUVec4,
+ EOpConstructMat2,
+ EOpConstructMat3,
+ EOpConstructMat4,
+ EOpConstructStruct,
+
+ //
+ // moves
+ //
+
+ EOpAssign,
+ EOpInitialize,
+ EOpAddAssign,
+ EOpSubAssign,
+ EOpMulAssign,
+ EOpVectorTimesMatrixAssign,
+ EOpVectorTimesScalarAssign,
+ EOpMatrixTimesScalarAssign,
+ EOpMatrixTimesMatrixAssign,
+ EOpDivAssign
+};
+
+class TIntermTraverser;
+class TIntermAggregate;
+class TIntermBinary;
+class TIntermUnary;
+class TIntermConstantUnion;
+class TIntermSelection;
+class TIntermTyped;
+class TIntermSymbol;
+class TIntermLoop;
+class TInfoSink;
+class TIntermRaw;
+
+//
+// Base class for the tree nodes
+//
+class TIntermNode
+{
+ public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TIntermNode()
+ {
+ // TODO: Move this to TSourceLoc constructor
+ // after getting rid of TPublicType.
+ mLine.first_file = mLine.last_file = 0;
+ mLine.first_line = mLine.last_line = 0;
+ }
+ virtual ~TIntermNode() { }
+
+ const TSourceLoc &getLine() const { return mLine; }
+ void setLine(const TSourceLoc &l) { mLine = l; }
+
+ virtual void traverse(TIntermTraverser *) = 0;
+ virtual TIntermTyped *getAsTyped() { return 0; }
+ virtual TIntermConstantUnion *getAsConstantUnion() { return 0; }
+ virtual TIntermAggregate *getAsAggregate() { return 0; }
+ virtual TIntermBinary *getAsBinaryNode() { return 0; }
+ virtual TIntermUnary *getAsUnaryNode() { return 0; }
+ virtual TIntermSelection *getAsSelectionNode() { return 0; }
+ virtual TIntermSymbol *getAsSymbolNode() { return 0; }
+ virtual TIntermLoop *getAsLoopNode() { return 0; }
+ virtual TIntermRaw *getAsRawNode() { return 0; }
+
+ // Replace a child node. Return true if |original| is a child
+ // node and it is replaced; otherwise, return false.
+ virtual bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement) = 0;
+
+ // For traversing a tree in no particular order, but using
+ // heap memory.
+ virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const = 0;
+
+ protected:
+ TSourceLoc mLine;
+};
+
+//
+// This is just to help yacc.
+//
+struct TIntermNodePair
+{
+ TIntermNode *node1;
+ TIntermNode *node2;
+};
+
+//
+// Intermediate class for nodes that have a type.
+//
+class TIntermTyped : public TIntermNode
+{
+ public:
+ TIntermTyped(const TType &t) : mType(t) { }
+ virtual TIntermTyped *getAsTyped() { return this; }
+
+ virtual bool hasSideEffects() const = 0;
+
+ void setType(const TType &t) { mType = t; }
+ const TType &getType() const { return mType; }
+ TType *getTypePointer() { return &mType; }
+
+ TBasicType getBasicType() const { return mType.getBasicType(); }
+ TQualifier getQualifier() const { return mType.getQualifier(); }
+ TPrecision getPrecision() const { return mType.getPrecision(); }
+ int getCols() const { return mType.getCols(); }
+ int getRows() const { return mType.getRows(); }
+ int getNominalSize() const { return mType.getNominalSize(); }
+ int getSecondarySize() const { return mType.getSecondarySize(); }
+
+ bool isInterfaceBlock() const { return mType.isInterfaceBlock(); }
+ bool isMatrix() const { return mType.isMatrix(); }
+ bool isArray() const { return mType.isArray(); }
+ bool isVector() const { return mType.isVector(); }
+ bool isScalar() const { return mType.isScalar(); }
+ bool isScalarInt() const { return mType.isScalarInt(); }
+ const char *getBasicString() const { return mType.getBasicString(); }
+ const char *getQualifierString() const { return mType.getQualifierString(); }
+ TString getCompleteString() const { return mType.getCompleteString(); }
+
+ int getArraySize() const { return mType.getArraySize(); }
+
+ protected:
+ TType mType;
+};
+
+//
+// Handle for, do-while, and while loops.
+//
+enum TLoopType
+{
+ ELoopFor,
+ ELoopWhile,
+ ELoopDoWhile
+};
+
+class TIntermLoop : public TIntermNode
+{
+ public:
+ TIntermLoop(TLoopType type,
+ TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
+ TIntermNode *body)
+ : mType(type),
+ mInit(init),
+ mCond(cond),
+ mExpr(expr),
+ mBody(body),
+ mUnrollFlag(false) { }
+
+ virtual TIntermLoop *getAsLoopNode() { return this; }
+ virtual void traverse(TIntermTraverser *);
+ virtual bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement);
+
+ TLoopType getType() const { return mType; }
+ TIntermNode *getInit() { return mInit; }
+ TIntermTyped *getCondition() { return mCond; }
+ TIntermTyped *getExpression() { return mExpr; }
+ TIntermNode *getBody() { return mBody; }
+
+ void setUnrollFlag(bool flag) { mUnrollFlag = flag; }
+ bool getUnrollFlag() const { return mUnrollFlag; }
+
+ virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
+
+ protected:
+ TLoopType mType;
+ TIntermNode *mInit; // for-loop initialization
+ TIntermTyped *mCond; // loop exit condition
+ TIntermTyped *mExpr; // for-loop expression
+ TIntermNode *mBody; // loop body
+
+ bool mUnrollFlag; // Whether the loop should be unrolled or not.
+};
+
+//
+// Handle break, continue, return, and kill.
+//
+class TIntermBranch : public TIntermNode
+{
+ public:
+ TIntermBranch(TOperator op, TIntermTyped *e)
+ : mFlowOp(op),
+ mExpression(e) { }
+
+ virtual void traverse(TIntermTraverser *);
+ virtual bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement);
+
+ TOperator getFlowOp() { return mFlowOp; }
+ TIntermTyped* getExpression() { return mExpression; }
+
+ virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
+
+protected:
+ TOperator mFlowOp;
+ TIntermTyped *mExpression; // non-zero except for "return exp;" statements
+};
+
+//
+// Nodes that correspond to symbols or constants in the source code.
+//
+class TIntermSymbol : public TIntermTyped
+{
+ public:
+ // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym.
+ // If sym comes from per process globalpoolallocator, then it causes increased memory usage
+ // per compile it is essential to use "symbol = sym" to assign to symbol
+ TIntermSymbol(int id, const TString &symbol, const TType &type)
+ : TIntermTyped(type),
+ mId(id)
+ {
+ mSymbol = symbol;
+ }
+
+ virtual bool hasSideEffects() const { return false; }
+
+ int getId() const { return mId; }
+ const TString &getSymbol() const { return mSymbol; }
+
+ void setId(int newId) { mId = newId; }
+
+ virtual void traverse(TIntermTraverser *);
+ virtual TIntermSymbol *getAsSymbolNode() { return this; }
+ virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
+
+ virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
+
+ protected:
+ int mId;
+ TString mSymbol;
+};
+
+// A Raw node stores raw code, that the translator will insert verbatim
+// into the output stream. Useful for transformation operations that make
+// complex code that might not fit naturally into the GLSL model.
+class TIntermRaw : public TIntermTyped
+{
+ public:
+ TIntermRaw(const TType &type, const TString &rawText)
+ : TIntermTyped(type),
+ mRawText(rawText) { }
+
+ virtual bool hasSideEffects() const { return false; }
+
+ TString getRawText() const { return mRawText; }
+
+ virtual void traverse(TIntermTraverser *);
+
+ virtual TIntermRaw *getAsRawNode() { return this; }
+ virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
+ virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
+
+ protected:
+ TString mRawText;
+};
+
+class TIntermConstantUnion : public TIntermTyped
+{
+ public:
+ TIntermConstantUnion(ConstantUnion *unionPointer, const TType &type)
+ : TIntermTyped(type),
+ mUnionArrayPointer(unionPointer) { }
+
+ virtual bool hasSideEffects() const { return false; }
+
+ ConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; }
+
+ int getIConst(size_t index) const
+ {
+ return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0;
+ }
+ unsigned int getUConst(size_t index) const
+ {
+ return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0;
+ }
+ float getFConst(size_t index) const
+ {
+ return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f;
+ }
+ bool getBConst(size_t index) const
+ {
+ return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false;
+ }
+
+ virtual TIntermConstantUnion *getAsConstantUnion() { return this; }
+ virtual void traverse(TIntermTraverser *);
+ virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
+
+ TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &);
+
+ virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
+
+ protected:
+ ConstantUnion *mUnionArrayPointer;
+};
+
+//
+// Intermediate class for node types that hold operators.
+//
+class TIntermOperator : public TIntermTyped
+{
+ public:
+ TOperator getOp() const { return mOp; }
+ void setOp(TOperator op) { mOp = op; }
+
+ bool isAssignment() const;
+ bool isConstructor() const;
+
+ virtual bool hasSideEffects() const { return isAssignment(); }
+
+ protected:
+ TIntermOperator(TOperator op)
+ : TIntermTyped(TType(EbtFloat, EbpUndefined)),
+ mOp(op) {}
+ TIntermOperator(TOperator op, const TType &type)
+ : TIntermTyped(type),
+ mOp(op) {}
+
+ TOperator mOp;
+};
+
+//
+// Nodes for all the basic binary math operators.
+//
+class TIntermBinary : public TIntermOperator
+{
+ public:
+ TIntermBinary(TOperator op)
+ : TIntermOperator(op),
+ mAddIndexClamp(false) {}
+
+ virtual TIntermBinary *getAsBinaryNode() { return this; }
+ virtual void traverse(TIntermTraverser *);
+ virtual bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement);
+
+ virtual bool hasSideEffects() const
+ {
+ return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects();
+ }
+
+ void setLeft(TIntermTyped *node) { mLeft = node; }
+ void setRight(TIntermTyped *node) { mRight = node; }
+ TIntermTyped *getLeft() const { return mLeft; }
+ TIntermTyped *getRight() const { return mRight; }
+ bool promote(TInfoSink &);
+
+ void setAddIndexClamp() { mAddIndexClamp = true; }
+ bool getAddIndexClamp() { return mAddIndexClamp; }
+
+ virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
+
+ protected:
+ TIntermTyped* mLeft;
+ TIntermTyped* mRight;
+
+ // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
+ bool mAddIndexClamp;
+};
+
+//
+// Nodes for unary math operators.
+//
+class TIntermUnary : public TIntermOperator
+{
+ public:
+ TIntermUnary(TOperator op, const TType &type)
+ : TIntermOperator(op, type),
+ mOperand(NULL),
+ mUseEmulatedFunction(false) {}
+ TIntermUnary(TOperator op)
+ : TIntermOperator(op),
+ mOperand(NULL),
+ mUseEmulatedFunction(false) {}
+
+ virtual void traverse(TIntermTraverser *);
+ virtual TIntermUnary *getAsUnaryNode() { return this; }
+ virtual bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement);
+
+ virtual bool hasSideEffects() const
+ {
+ return isAssignment() || mOperand->hasSideEffects();
+ }
+
+ void setOperand(TIntermTyped *operand) { mOperand = operand; }
+ TIntermTyped *getOperand() { return mOperand; }
+ bool promote(TInfoSink &);
+
+ void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
+ bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
+
+ virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
+
+ protected:
+ TIntermTyped *mOperand;
+
+ // If set to true, replace the built-in function call with an emulated one
+ // to work around driver bugs.
+ bool mUseEmulatedFunction;
+};
+
+typedef TVector<TIntermNode *> TIntermSequence;
+typedef TVector<int> TQualifierList;
+
+//
+// Nodes that operate on an arbitrary sized set of children.
+//
+class TIntermAggregate : public TIntermOperator
+{
+ public:
+ TIntermAggregate()
+ : TIntermOperator(EOpNull),
+ mUserDefined(false),
+ mUseEmulatedFunction(false) { }
+ TIntermAggregate(TOperator op)
+ : TIntermOperator(op),
+ mUseEmulatedFunction(false) { }
+ ~TIntermAggregate() { }
+
+ virtual TIntermAggregate *getAsAggregate() { return this; }
+ virtual void traverse(TIntermTraverser *);
+ virtual bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement);
+
+ // Conservatively assume function calls and other aggregate operators have side-effects
+ virtual bool hasSideEffects() const { return true; }
+
+ TIntermSequence *getSequence() { return &mSequence; }
+
+ void setName(const TString &name) { mName = name; }
+ const TString &getName() const { return mName; }
+
+ void setUserDefined() { mUserDefined = true; }
+ bool isUserDefined() const { return mUserDefined; }
+
+ void setOptimize(bool optimize) { mOptimize = optimize; }
+ bool getOptimize() const { return mOptimize; }
+ void setDebug(bool debug) { mDebug = debug; }
+ bool getDebug() const { return mDebug; }
+
+ void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
+ bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
+
+ virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
+
+ protected:
+ TIntermAggregate(const TIntermAggregate &); // disallow copy constructor
+ TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator
+ TIntermSequence mSequence;
+ TString mName;
+ bool mUserDefined; // used for user defined function names
+
+ bool mOptimize;
+ bool mDebug;
+
+ // If set to true, replace the built-in function call with an emulated one
+ // to work around driver bugs.
+ bool mUseEmulatedFunction;
+};
+
+//
+// For if tests. Simplified since there is no switch statement.
+//
+class TIntermSelection : public TIntermTyped
+{
+ public:
+ TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB)
+ : TIntermTyped(TType(EbtVoid, EbpUndefined)),
+ mCondition(cond),
+ mTrueBlock(trueB),
+ mFalseBlock(falseB) {}
+ TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB,
+ const TType &type)
+ : TIntermTyped(type),
+ mCondition(cond),
+ mTrueBlock(trueB),
+ mFalseBlock(falseB) {}
+
+ virtual void traverse(TIntermTraverser *);
+ virtual bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement);
+
+ // Conservatively assume selections have side-effects
+ virtual bool hasSideEffects() const { return true; }
+
+ bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
+ TIntermNode *getCondition() const { return mCondition; }
+ TIntermNode *getTrueBlock() const { return mTrueBlock; }
+ TIntermNode *getFalseBlock() const { return mFalseBlock; }
+ TIntermSelection *getAsSelectionNode() { return this; }
+
+ virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
+
+protected:
+ TIntermTyped *mCondition;
+ TIntermNode *mTrueBlock;
+ TIntermNode *mFalseBlock;
+};
+
+enum Visit
+{
+ PreVisit,
+ InVisit,
+ PostVisit
+};
+
+//
+// For traversing the tree. User should derive from this,
+// put their traversal specific data in it, and then pass
+// it to a Traverse method.
+//
+// When using this, just fill in the methods for nodes you want visited.
+// Return false from a pre-visit to skip visiting that node's subtree.
+//
+class TIntermTraverser
+{
+ public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ // TODO(zmo): remove default values.
+ TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false,
+ bool rightToLeft = false)
+ : preVisit(preVisit),
+ inVisit(inVisit),
+ postVisit(postVisit),
+ rightToLeft(rightToLeft),
+ mDepth(0),
+ mMaxDepth(0) {}
+ virtual ~TIntermTraverser() {}
+
+ virtual void visitSymbol(TIntermSymbol *) {}
+ virtual void visitRaw(TIntermRaw *) {}
+ virtual void visitConstantUnion(TIntermConstantUnion *) {}
+ virtual bool visitBinary(Visit, TIntermBinary *) { return true; }
+ virtual bool visitUnary(Visit, TIntermUnary *) { return true; }
+ virtual bool visitSelection(Visit, TIntermSelection *) { return true; }
+ virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; }
+ virtual bool visitLoop(Visit, TIntermLoop *) { return true; }
+ virtual bool visitBranch(Visit, TIntermBranch *) { return true; }
+
+ int getMaxDepth() const { return mMaxDepth; }
+
+ void incrementDepth(TIntermNode *current)
+ {
+ mDepth++;
+ mMaxDepth = std::max(mMaxDepth, mDepth);
+ mPath.push_back(current);
+ }
+
+ void decrementDepth()
+ {
+ mDepth--;
+ mPath.pop_back();
+ }
+
+ TIntermNode *getParentNode()
+ {
+ return mPath.size() == 0 ? NULL : mPath.back();
+ }
+
+ // Return the original name if hash function pointer is NULL;
+ // otherwise return the hashed name.
+ static TString hash(const TString& name, ShHashFunction64 hashFunction);
+
+ const bool preVisit;
+ const bool inVisit;
+ const bool postVisit;
+ const bool rightToLeft;
+
+ protected:
+ int mDepth;
+ int mMaxDepth;
+
+ // All the nodes from root to the current node's parent during traversing.
+ TVector<TIntermNode *> mPath;
+};
+
+//
+// For traversing the tree, and computing max depth.
+// Takes a maximum depth limit to prevent stack overflow.
+//
+class TMaxDepthTraverser : public TIntermTraverser
+{
+ public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TMaxDepthTraverser(int depthLimit)
+ : TIntermTraverser(true, true, false, false),
+ mDepthLimit(depthLimit) { }
+
+ virtual bool visitBinary(Visit, TIntermBinary *) { return depthCheck(); }
+ virtual bool visitUnary(Visit, TIntermUnary *) { return depthCheck(); }
+ virtual bool visitSelection(Visit, TIntermSelection *) { return depthCheck(); }
+ virtual bool visitAggregate(Visit, TIntermAggregate *) { return depthCheck(); }
+ virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); }
+ virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); }
+
+protected:
+ bool depthCheck() const { return mMaxDepth < mDepthLimit; }
+
+ int mDepthLimit;
+};
+
+#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_
diff --git a/src/compiler/translator/IntermTraverse.cpp b/src/compiler/translator/IntermTraverse.cpp
index 48d2013..72b2033 100644
--- a/src/compiler/translator/IntermTraverse.cpp
+++ b/src/compiler/translator/IntermTraverse.cpp
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
//
// Traverse the intermediate representation tree, and
diff --git a/src/compiler/translator/Intermediate.cpp b/src/compiler/translator/Intermediate.cpp
index fa0c9f7..ef4f833 100644
--- a/src/compiler/translator/Intermediate.cpp
+++ b/src/compiler/translator/Intermediate.cpp
@@ -12,122 +12,10 @@
#include <limits.h>
#include <algorithm>
-#include "compiler/translator/HashNames.h"
-#include "compiler/translator/localintermediate.h"
-#include "compiler/translator/QualifierAlive.h"
+#include "compiler/translator/Intermediate.h"
#include "compiler/translator/RemoveTree.h"
#include "compiler/translator/SymbolTable.h"
-namespace
-{
-
-TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
-{
- return left > right ? left : right;
-}
-
-bool ValidateMultiplication(TOperator op, const TType &left, const TType &right)
-{
- switch (op)
- {
- case EOpMul:
- case EOpMulAssign:
- return left.getNominalSize() == right.getNominalSize() &&
- left.getSecondarySize() == right.getSecondarySize();
- case EOpVectorTimesScalar:
- case EOpVectorTimesScalarAssign:
- return true;
- case EOpVectorTimesMatrix:
- return left.getNominalSize() == right.getRows();
- case EOpVectorTimesMatrixAssign:
- return left.getNominalSize() == right.getRows() &&
- left.getNominalSize() == right.getCols();
- case EOpMatrixTimesVector:
- return left.getCols() == right.getNominalSize();
- case EOpMatrixTimesScalar:
- case EOpMatrixTimesScalarAssign:
- return true;
- case EOpMatrixTimesMatrix:
- return left.getCols() == right.getRows();
- case EOpMatrixTimesMatrixAssign:
- return left.getCols() == right.getCols() &&
- left.getRows() == right.getRows();
-
- default:
- UNREACHABLE();
- return false;
- }
-}
-
-bool CompareStructure(const TType& leftNodeType,
- ConstantUnion *rightUnionArray,
- ConstantUnion *leftUnionArray);
-
-bool CompareStruct(const TType &leftNodeType,
- ConstantUnion *rightUnionArray,
- ConstantUnion *leftUnionArray)
-{
- const TFieldList &fields = leftNodeType.getStruct()->fields();
-
- size_t structSize = fields.size();
- size_t index = 0;
-
- for (size_t j = 0; j < structSize; j++)
- {
- size_t size = fields[j]->type()->getObjectSize();
- for (size_t i = 0; i < size; i++)
- {
- if (fields[j]->type()->getBasicType() == EbtStruct)
- {
- if (!CompareStructure(*fields[j]->type(),
- &rightUnionArray[index],
- &leftUnionArray[index]))
- {
- return false;
- }
- }
- else
- {
- if (leftUnionArray[index] != rightUnionArray[index])
- return false;
- index++;
- }
- }
- }
- return true;
-}
-
-bool CompareStructure(const TType &leftNodeType,
- ConstantUnion *rightUnionArray,
- ConstantUnion *leftUnionArray)
-{
- if (leftNodeType.isArray())
- {
- TType typeWithoutArrayness = leftNodeType;
- typeWithoutArrayness.clearArrayness();
-
- size_t arraySize = leftNodeType.getArraySize();
-
- for (size_t i = 0; i < arraySize; ++i)
- {
- size_t offset = typeWithoutArrayness.getObjectSize() * i;
- if (!CompareStruct(typeWithoutArrayness,
- &rightUnionArray[offset],
- &leftUnionArray[offset]))
- {
- return false;
- }
- }
- }
- else
- {
- return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
- }
- return true;
-}
-
-} // namespace anonymous
-
////////////////////////////////////////////////////////////////////////////
//
// First set of functions are to help build the intermediate representation.
@@ -630,982 +518,3 @@
if (root)
RemoveAllTreeNodes(root);
}
-
-////////////////////////////////////////////////////////////////
-//
-// Member functions of the nodes used for building the tree.
-//
-////////////////////////////////////////////////////////////////
-
-#define REPLACE_IF_IS(node, type, original, replacement) \
- if (node == original) { \
- node = static_cast<type *>(replacement); \
- return true; \
- }
-
-bool TIntermLoop::replaceChildNode(
- TIntermNode *original, TIntermNode *replacement)
-{
- REPLACE_IF_IS(mInit, TIntermNode, original, replacement);
- REPLACE_IF_IS(mCond, TIntermTyped, original, replacement);
- REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement);
- REPLACE_IF_IS(mBody, TIntermNode, original, replacement);
- return false;
-}
-
-void TIntermLoop::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
-{
- if (mInit)
- {
- nodeQueue->push(mInit);
- }
- if (mCond)
- {
- nodeQueue->push(mCond);
- }
- if (mExpr)
- {
- nodeQueue->push(mExpr);
- }
- if (mBody)
- {
- nodeQueue->push(mBody);
- }
-}
-
-bool TIntermBranch::replaceChildNode(
- TIntermNode *original, TIntermNode *replacement)
-{
- REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement);
- return false;
-}
-
-void TIntermBranch::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
-{
- if (mExpression)
- {
- nodeQueue->push(mExpression);
- }
-}
-
-bool TIntermBinary::replaceChildNode(
- TIntermNode *original, TIntermNode *replacement)
-{
- REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement);
- REPLACE_IF_IS(mRight, TIntermTyped, original, replacement);
- return false;
-}
-
-void TIntermBinary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
-{
- if (mLeft)
- {
- nodeQueue->push(mLeft);
- }
- if (mRight)
- {
- nodeQueue->push(mRight);
- }
-}
-
-bool TIntermUnary::replaceChildNode(
- TIntermNode *original, TIntermNode *replacement)
-{
- REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
- return false;
-}
-
-void TIntermUnary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
-{
- if (mOperand)
- {
- nodeQueue->push(mOperand);
- }
-}
-
-bool TIntermAggregate::replaceChildNode(
- TIntermNode *original, TIntermNode *replacement)
-{
- for (size_t ii = 0; ii < mSequence.size(); ++ii)
- {
- REPLACE_IF_IS(mSequence[ii], TIntermNode, original, replacement);
- }
- return false;
-}
-
-void TIntermAggregate::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
-{
- for (size_t childIndex = 0; childIndex < mSequence.size(); childIndex++)
- {
- nodeQueue->push(mSequence[childIndex]);
- }
-}
-
-bool TIntermSelection::replaceChildNode(
- TIntermNode *original, TIntermNode *replacement)
-{
- REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
- REPLACE_IF_IS(mTrueBlock, TIntermNode, original, replacement);
- REPLACE_IF_IS(mFalseBlock, TIntermNode, original, replacement);
- return false;
-}
-
-void TIntermSelection::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
-{
- if (mCondition)
- {
- nodeQueue->push(mCondition);
- }
- if (mTrueBlock)
- {
- nodeQueue->push(mTrueBlock);
- }
- if (mFalseBlock)
- {
- nodeQueue->push(mFalseBlock);
- }
-}
-
-//
-// Say whether or not an operation node changes the value of a variable.
-//
-bool TIntermOperator::isAssignment() const
-{
- switch (mOp)
- {
- case EOpPostIncrement:
- case EOpPostDecrement:
- case EOpPreIncrement:
- case EOpPreDecrement:
- case EOpAssign:
- case EOpAddAssign:
- case EOpSubAssign:
- case EOpMulAssign:
- case EOpVectorTimesMatrixAssign:
- case EOpVectorTimesScalarAssign:
- case EOpMatrixTimesScalarAssign:
- case EOpMatrixTimesMatrixAssign:
- case EOpDivAssign:
- return true;
- default:
- return false;
- }
-}
-
-//
-// returns true if the operator is for one of the constructors
-//
-bool TIntermOperator::isConstructor() const
-{
- switch (mOp)
- {
- case EOpConstructVec2:
- case EOpConstructVec3:
- case EOpConstructVec4:
- case EOpConstructMat2:
- case EOpConstructMat3:
- case EOpConstructMat4:
- case EOpConstructFloat:
- case EOpConstructIVec2:
- case EOpConstructIVec3:
- case EOpConstructIVec4:
- case EOpConstructInt:
- case EOpConstructUVec2:
- case EOpConstructUVec3:
- case EOpConstructUVec4:
- case EOpConstructUInt:
- case EOpConstructBVec2:
- case EOpConstructBVec3:
- case EOpConstructBVec4:
- case EOpConstructBool:
- case EOpConstructStruct:
- return true;
- default:
- return false;
- }
-}
-
-//
-// Make sure the type of a unary operator is appropriate for its
-// combination of operation and operand type.
-//
-// Returns false in nothing makes sense.
-//
-bool TIntermUnary::promote(TInfoSink &)
-{
- switch (mOp)
- {
- case EOpLogicalNot:
- if (mOperand->getBasicType() != EbtBool)
- return false;
- break;
- case EOpNegative:
- case EOpPostIncrement:
- case EOpPostDecrement:
- case EOpPreIncrement:
- case EOpPreDecrement:
- if (mOperand->getBasicType() == EbtBool)
- return false;
- break;
-
- // operators for built-ins are already type checked against their prototype
- case EOpAny:
- case EOpAll:
- case EOpVectorLogicalNot:
- return true;
-
- default:
- if (mOperand->getBasicType() != EbtFloat)
- return false;
- }
-
- setType(mOperand->getType());
- mType.setQualifier(EvqTemporary);
-
- return true;
-}
-
-//
-// Establishes the type of the resultant operation, as well as
-// makes the operator the correct one for the operands.
-//
-// Returns false if operator can't work on operands.
-//
-bool TIntermBinary::promote(TInfoSink &infoSink)
-{
- // This function only handles scalars, vectors, and matrices.
- if (mLeft->isArray() || mRight->isArray())
- {
- infoSink.info.message(EPrefixInternalError, getLine(),
- "Invalid operation for arrays");
- return false;
- }
-
- // GLSL ES 2.0 does not support implicit type casting.
- // So the basic type should always match.
- if (mLeft->getBasicType() != mRight->getBasicType())
- {
- return false;
- }
-
- //
- // Base assumption: just make the type the same as the left
- // operand. Then only deviations from this need be coded.
- //
- setType(mLeft->getType());
-
- // The result gets promoted to the highest precision.
- TPrecision higherPrecision = GetHigherPrecision(
- mLeft->getPrecision(), mRight->getPrecision());
- getTypePointer()->setPrecision(higherPrecision);
-
- // Binary operations results in temporary variables unless both
- // operands are const.
- if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst)
- {
- getTypePointer()->setQualifier(EvqTemporary);
- }
-
- const int nominalSize =
- std::max(mLeft->getNominalSize(), mRight->getNominalSize());
-
- //
- // All scalars or structs. Code after this test assumes this case is removed!
- //
- if (nominalSize == 1)
- {
- switch (mOp)
- {
- //
- // Promote to conditional
- //
- case EOpEqual:
- case EOpNotEqual:
- case EOpLessThan:
- case EOpGreaterThan:
- case EOpLessThanEqual:
- case EOpGreaterThanEqual:
- setType(TType(EbtBool, EbpUndefined));
- break;
-
- //
- // And and Or operate on conditionals
- //
- case EOpLogicalAnd:
- case EOpLogicalOr:
- // Both operands must be of type bool.
- if (mLeft->getBasicType() != EbtBool || mRight->getBasicType() != EbtBool)
- {
- return false;
- }
- setType(TType(EbtBool, EbpUndefined));
- break;
-
- default:
- break;
- }
- return true;
- }
-
- // If we reach here, at least one of the operands is vector or matrix.
- // The other operand could be a scalar, vector, or matrix.
- // Can these two operands be combined?
- //
- TBasicType basicType = mLeft->getBasicType();
- switch (mOp)
- {
- case EOpMul:
- if (!mLeft->isMatrix() && mRight->isMatrix())
- {
- if (mLeft->isVector())
- {
- mOp = EOpVectorTimesMatrix;
- setType(TType(basicType, higherPrecision, EvqTemporary,
- mRight->getCols(), 1));
- }
- else
- {
- mOp = EOpMatrixTimesScalar;
- setType(TType(basicType, higherPrecision, EvqTemporary,
- mRight->getCols(), mRight->getRows()));
- }
- }
- else if (mLeft->isMatrix() && !mRight->isMatrix())
- {
- if (mRight->isVector())
- {
- mOp = EOpMatrixTimesVector;
- setType(TType(basicType, higherPrecision, EvqTemporary,
- mLeft->getRows(), 1));
- }
- else
- {
- mOp = EOpMatrixTimesScalar;
- }
- }
- else if (mLeft->isMatrix() && mRight->isMatrix())
- {
- mOp = EOpMatrixTimesMatrix;
- setType(TType(basicType, higherPrecision, EvqTemporary,
- mRight->getCols(), mLeft->getRows()));
- }
- else if (!mLeft->isMatrix() && !mRight->isMatrix())
- {
- if (mLeft->isVector() && mRight->isVector())
- {
- // leave as component product
- }
- else if (mLeft->isVector() || mRight->isVector())
- {
- mOp = EOpVectorTimesScalar;
- setType(TType(basicType, higherPrecision, EvqTemporary,
- nominalSize, 1));
- }
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(),
- "Missing elses");
- return false;
- }
-
- if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType()))
- {
- return false;
- }
- break;
-
- case EOpMulAssign:
- if (!mLeft->isMatrix() && mRight->isMatrix())
- {
- if (mLeft->isVector())
- {
- mOp = EOpVectorTimesMatrixAssign;
- }
- else
- {
- return false;
- }
- }
- else if (mLeft->isMatrix() && !mRight->isMatrix())
- {
- if (mRight->isVector())
- {
- return false;
- }
- else
- {
- mOp = EOpMatrixTimesScalarAssign;
- }
- }
- else if (mLeft->isMatrix() && mRight->isMatrix())
- {
- mOp = EOpMatrixTimesMatrixAssign;
- setType(TType(basicType, higherPrecision, EvqTemporary,
- mRight->getCols(), mLeft->getRows()));
- }
- else if (!mLeft->isMatrix() && !mRight->isMatrix())
- {
- if (mLeft->isVector() && mRight->isVector())
- {
- // leave as component product
- }
- else if (mLeft->isVector() || mRight->isVector())
- {
- if (!mLeft->isVector())
- return false;
- mOp = EOpVectorTimesScalarAssign;
- setType(TType(basicType, higherPrecision, EvqTemporary,
- mLeft->getNominalSize(), 1));
- }
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(),
- "Missing elses");
- return false;
- }
-
- if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType()))
- {
- return false;
- }
- break;
-
- case EOpAssign:
- case EOpInitialize:
- case EOpAdd:
- case EOpSub:
- case EOpDiv:
- case EOpAddAssign:
- case EOpSubAssign:
- case EOpDivAssign:
- if ((mLeft->isMatrix() && mRight->isVector()) ||
- (mLeft->isVector() && mRight->isMatrix()))
- {
- return false;
- }
-
- // Are the sizes compatible?
- if (mLeft->getNominalSize() != mRight->getNominalSize() ||
- mLeft->getSecondarySize() != mRight->getSecondarySize())
- {
- // If the nominal size of operands do not match:
- // One of them must be scalar.
- if (!mLeft->isScalar() && !mRight->isScalar())
- return false;
-
- // Operator cannot be of type pure assignment.
- if (mOp == EOpAssign || mOp == EOpInitialize)
- return false;
- }
-
- {
- const int secondarySize = std::max(
- mLeft->getSecondarySize(), mRight->getSecondarySize());
- setType(TType(basicType, higherPrecision, EvqTemporary,
- nominalSize, secondarySize));
- }
- break;
-
- case EOpEqual:
- case EOpNotEqual:
- case EOpLessThan:
- case EOpGreaterThan:
- case EOpLessThanEqual:
- case EOpGreaterThanEqual:
- if ((mLeft->getNominalSize() != mRight->getNominalSize()) ||
- (mLeft->getSecondarySize() != mRight->getSecondarySize()))
- {
- return false;
- }
- setType(TType(EbtBool, EbpUndefined));
- break;
-
- default:
- return false;
- }
- return true;
-}
-
-//
-// The fold functions see if an operation on a constant can be done in place,
-// without generating run-time code.
-//
-// Returns the node to keep using, which may or may not be the node passed in.
-//
-TIntermTyped *TIntermConstantUnion::fold(
- TOperator op, TIntermTyped *constantNode, TInfoSink &infoSink)
-{
- ConstantUnion *unionArray = getUnionArrayPointer();
-
- if (!unionArray)
- return NULL;
-
- size_t objectSize = getType().getObjectSize();
-
- if (constantNode)
- {
- // binary operations
- TIntermConstantUnion *node = constantNode->getAsConstantUnion();
- ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
- TType returnType = getType();
-
- if (!rightUnionArray)
- return NULL;
-
- // for a case like float f = 1.2 + vec4(2,3,4,5);
- if (constantNode->getType().getObjectSize() == 1 && objectSize > 1)
- {
- rightUnionArray = new ConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; ++i)
- {
- rightUnionArray[i] = *node->getUnionArrayPointer();
- }
- returnType = getType();
- }
- else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1)
- {
- // for a case like float f = vec4(2,3,4,5) + 1.2;
- unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
- for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
- {
- unionArray[i] = *getUnionArrayPointer();
- }
- returnType = node->getType();
- objectSize = constantNode->getType().getObjectSize();
- }
-
- ConstantUnion *tempConstArray = NULL;
- TIntermConstantUnion *tempNode;
-
- bool boolNodeFlag = false;
- switch(op)
- {
- case EOpAdd:
- tempConstArray = new ConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- tempConstArray[i] = unionArray[i] + rightUnionArray[i];
- break;
- case EOpSub:
- tempConstArray = new ConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- tempConstArray[i] = unionArray[i] - rightUnionArray[i];
- break;
-
- case EOpMul:
- case EOpVectorTimesScalar:
- case EOpMatrixTimesScalar:
- tempConstArray = new ConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- tempConstArray[i] = unionArray[i] * rightUnionArray[i];
- break;
-
- case EOpMatrixTimesMatrix:
- {
- if (getType().getBasicType() != EbtFloat ||
- node->getBasicType() != EbtFloat)
- {
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Constant Folding cannot be done for matrix multiply");
- return NULL;
- }
-
- const int leftCols = getCols();
- const int leftRows = getRows();
- const int rightCols = constantNode->getType().getCols();
- const int rightRows = constantNode->getType().getRows();
- const int resultCols = rightCols;
- const int resultRows = leftRows;
-
- tempConstArray = new ConstantUnion[resultCols*resultRows];
- for (int row = 0; row < resultRows; row++)
- {
- for (int column = 0; column < resultCols; column++)
- {
- tempConstArray[resultRows * column + row].setFConst(0.0f);
- for (int i = 0; i < leftCols; i++)
- {
- tempConstArray[resultRows * column + row].setFConst(
- tempConstArray[resultRows * column + row].getFConst() +
- unionArray[i * leftRows + row].getFConst() *
- rightUnionArray[column * rightRows + i].getFConst());
- }
- }
- }
-
- // update return type for matrix product
- returnType.setPrimarySize(resultCols);
- returnType.setSecondarySize(resultRows);
- }
- break;
-
- case EOpDiv:
- {
- tempConstArray = new ConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- {
- switch (getType().getBasicType())
- {
- case EbtFloat:
- if (rightUnionArray[i] == 0.0f)
- {
- infoSink.info.message(
- EPrefixWarning, getLine(),
- "Divide by zero error during constant folding");
- tempConstArray[i].setFConst(
- unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
- }
- else
- {
- tempConstArray[i].setFConst(
- unionArray[i].getFConst() /
- rightUnionArray[i].getFConst());
- }
- break;
-
- case EbtInt:
- if (rightUnionArray[i] == 0)
- {
- infoSink.info.message(
- EPrefixWarning, getLine(),
- "Divide by zero error during constant folding");
- tempConstArray[i].setIConst(INT_MAX);
- }
- else
- {
- tempConstArray[i].setIConst(
- unionArray[i].getIConst() /
- rightUnionArray[i].getIConst());
- }
- break;
-
- case EbtUInt:
- if (rightUnionArray[i] == 0)
- {
- infoSink.info.message(
- EPrefixWarning, getLine(),
- "Divide by zero error during constant folding");
- tempConstArray[i].setUConst(UINT_MAX);
- }
- else
- {
- tempConstArray[i].setUConst(
- unionArray[i].getUConst() /
- rightUnionArray[i].getUConst());
- }
- break;
-
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Constant folding cannot be done for \"/\"");
- return NULL;
- }
- }
- }
- break;
-
- case EOpMatrixTimesVector:
- {
- if (node->getBasicType() != EbtFloat)
- {
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Constant Folding cannot be done for matrix times vector");
- return NULL;
- }
-
- const int matrixCols = getCols();
- const int matrixRows = getRows();
-
- tempConstArray = new ConstantUnion[matrixRows];
-
- for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
- {
- tempConstArray[matrixRow].setFConst(0.0f);
- for (int col = 0; col < matrixCols; col++)
- {
- tempConstArray[matrixRow].setFConst(
- tempConstArray[matrixRow].getFConst() +
- unionArray[col * matrixRows + matrixRow].getFConst() *
- rightUnionArray[col].getFConst());
- }
- }
-
- returnType = node->getType();
- returnType.setPrimarySize(matrixRows);
-
- tempNode = new TIntermConstantUnion(tempConstArray, returnType);
- tempNode->setLine(getLine());
-
- return tempNode;
- }
-
- case EOpVectorTimesMatrix:
- {
- if (getType().getBasicType() != EbtFloat)
- {
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Constant Folding cannot be done for vector times matrix");
- return NULL;
- }
-
- const int matrixCols = constantNode->getType().getCols();
- const int matrixRows = constantNode->getType().getRows();
-
- tempConstArray = new ConstantUnion[matrixCols];
-
- for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++)
- {
- tempConstArray[matrixCol].setFConst(0.0f);
- for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
- {
- tempConstArray[matrixCol].setFConst(
- tempConstArray[matrixCol].getFConst() +
- unionArray[matrixRow].getFConst() *
- rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst());
- }
- }
-
- returnType.setPrimarySize(matrixCols);
- }
- break;
-
- case EOpLogicalAnd:
- // this code is written for possible future use,
- // will not get executed currently
- {
- tempConstArray = new ConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- {
- tempConstArray[i] = unionArray[i] && rightUnionArray[i];
- }
- }
- break;
-
- case EOpLogicalOr:
- // this code is written for possible future use,
- // will not get executed currently
- {
- tempConstArray = new ConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- {
- tempConstArray[i] = unionArray[i] || rightUnionArray[i];
- }
- }
- break;
-
- case EOpLogicalXor:
- {
- tempConstArray = new ConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- {
- switch (getType().getBasicType())
- {
- case EbtBool:
- tempConstArray[i].setBConst(
- unionArray[i] == rightUnionArray[i] ? false : true);
- break;
- default:
- UNREACHABLE();
- break;
- }
- }
- }
- break;
-
- case EOpLessThan:
- ASSERT(objectSize == 1);
- tempConstArray = new ConstantUnion[1];
- tempConstArray->setBConst(*unionArray < *rightUnionArray);
- returnType = TType(EbtBool, EbpUndefined, EvqConst);
- break;
-
- case EOpGreaterThan:
- ASSERT(objectSize == 1);
- tempConstArray = new ConstantUnion[1];
- tempConstArray->setBConst(*unionArray > *rightUnionArray);
- returnType = TType(EbtBool, EbpUndefined, EvqConst);
- break;
-
- case EOpLessThanEqual:
- {
- ASSERT(objectSize == 1);
- ConstantUnion constant;
- constant.setBConst(*unionArray > *rightUnionArray);
- tempConstArray = new ConstantUnion[1];
- tempConstArray->setBConst(!constant.getBConst());
- returnType = TType(EbtBool, EbpUndefined, EvqConst);
- break;
- }
-
- case EOpGreaterThanEqual:
- {
- ASSERT(objectSize == 1);
- ConstantUnion constant;
- constant.setBConst(*unionArray < *rightUnionArray);
- tempConstArray = new ConstantUnion[1];
- tempConstArray->setBConst(!constant.getBConst());
- returnType = TType(EbtBool, EbpUndefined, EvqConst);
- break;
- }
-
- case EOpEqual:
- if (getType().getBasicType() == EbtStruct)
- {
- if (!CompareStructure(node->getType(),
- node->getUnionArrayPointer(),
- unionArray))
- {
- boolNodeFlag = true;
- }
- }
- else
- {
- for (size_t i = 0; i < objectSize; i++)
- {
- if (unionArray[i] != rightUnionArray[i])
- {
- boolNodeFlag = true;
- break; // break out of for loop
- }
- }
- }
-
- tempConstArray = new ConstantUnion[1];
- if (!boolNodeFlag)
- {
- tempConstArray->setBConst(true);
- }
- else
- {
- tempConstArray->setBConst(false);
- }
-
- tempNode = new TIntermConstantUnion(
- tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
- tempNode->setLine(getLine());
-
- return tempNode;
-
- case EOpNotEqual:
- if (getType().getBasicType() == EbtStruct)
- {
- if (CompareStructure(node->getType(),
- node->getUnionArrayPointer(),
- unionArray))
- {
- boolNodeFlag = true;
- }
- }
- else
- {
- for (size_t i = 0; i < objectSize; i++)
- {
- if (unionArray[i] == rightUnionArray[i])
- {
- boolNodeFlag = true;
- break; // break out of for loop
- }
- }
- }
-
- tempConstArray = new ConstantUnion[1];
- if (!boolNodeFlag)
- {
- tempConstArray->setBConst(true);
- }
- else
- {
- tempConstArray->setBConst(false);
- }
-
- tempNode = new TIntermConstantUnion(
- tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
- tempNode->setLine(getLine());
-
- return tempNode;
-
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Invalid operator for constant folding");
- return NULL;
- }
- tempNode = new TIntermConstantUnion(tempConstArray, returnType);
- tempNode->setLine(getLine());
-
- return tempNode;
- }
- else
- {
- //
- // Do unary operations
- //
- TIntermConstantUnion *newNode = 0;
- ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- {
- switch(op)
- {
- case EOpNegative:
- switch (getType().getBasicType())
- {
- case EbtFloat:
- tempConstArray[i].setFConst(-unionArray[i].getFConst());
- break;
- case EbtInt:
- tempConstArray[i].setIConst(-unionArray[i].getIConst());
- break;
- case EbtUInt:
- tempConstArray[i].setUConst(static_cast<unsigned int>(
- -static_cast<int>(unionArray[i].getUConst())));
- break;
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return NULL;
- }
- break;
-
- case EOpLogicalNot:
- // this code is written for possible future use,
- // will not get executed currently
- switch (getType().getBasicType())
- {
- case EbtBool:
- tempConstArray[i].setBConst(!unionArray[i].getBConst());
- break;
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return NULL;
- }
- break;
-
- default:
- return NULL;
- }
- }
- newNode = new TIntermConstantUnion(tempConstArray, getType());
- newNode->setLine(getLine());
- return newNode;
- }
-}
-
-// static
-TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction)
-{
- if (hashFunction == NULL || name.empty())
- return name;
- khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
- TStringStream stream;
- stream << HASHED_NAME_PREFIX << std::hex << number;
- TString hashedName = stream.str();
- return hashedName;
-}
diff --git a/src/compiler/translator/LoopInfo.h b/src/compiler/translator/LoopInfo.h
index 5a140c3..5f72a6e 100644
--- a/src/compiler/translator/LoopInfo.h
+++ b/src/compiler/translator/LoopInfo.h
@@ -7,7 +7,7 @@
#ifndef COMPILER_TRANSLATOR_LOOP_INFO_H_
#define COMPILER_TRANSLATOR_LOOP_INFO_H_
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
class TLoopIndexInfo
{
diff --git a/src/compiler/translator/NodeSearch.h b/src/compiler/translator/NodeSearch.h
index b58c7ec..60070c9 100644
--- a/src/compiler/translator/NodeSearch.h
+++ b/src/compiler/translator/NodeSearch.h
@@ -9,7 +9,7 @@
#ifndef TRANSLATOR_NODESEARCH_H_
#define TRANSLATOR_NODESEARCH_H_
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
namespace sh
{
diff --git a/src/compiler/translator/OutputGLSLBase.h b/src/compiler/translator/OutputGLSLBase.h
index 42364de..e5174f5 100644
--- a/src/compiler/translator/OutputGLSLBase.h
+++ b/src/compiler/translator/OutputGLSLBase.h
@@ -9,7 +9,7 @@
#include <set>
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
#include "compiler/translator/LoopInfo.h"
#include "compiler/translator/ParseContext.h"
diff --git a/src/compiler/translator/OutputHLSL.h b/src/compiler/translator/OutputHLSL.h
index eb34aa2..61afc41 100644
--- a/src/compiler/translator/OutputHLSL.h
+++ b/src/compiler/translator/OutputHLSL.h
@@ -13,7 +13,7 @@
#include "angle_gl.h"
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
#include "compiler/translator/ParseContext.h"
namespace sh
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
index a402eec..a6625d9 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -9,7 +9,7 @@
#include "compiler/translator/Compiler.h"
#include "compiler/translator/Diagnostics.h"
#include "compiler/translator/DirectiveHandler.h"
-#include "compiler/translator/localintermediate.h"
+#include "compiler/translator/Intermediate.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/preprocessor/Preprocessor.h"
diff --git a/src/compiler/translator/QualifierAlive.cpp b/src/compiler/translator/QualifierAlive.cpp
index 1ba087e..1f6fb75 100644
--- a/src/compiler/translator/QualifierAlive.cpp
+++ b/src/compiler/translator/QualifierAlive.cpp
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
class TAliveTraverser : public TIntermTraverser {
public:
diff --git a/src/compiler/translator/RemoveTree.cpp b/src/compiler/translator/RemoveTree.cpp
index e381c32..0cf6910 100644
--- a/src/compiler/translator/RemoveTree.cpp
+++ b/src/compiler/translator/RemoveTree.cpp
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
#include "compiler/translator/RemoveTree.h"
//
diff --git a/src/compiler/translator/RenameFunction.h b/src/compiler/translator/RenameFunction.h
index 1f7fb16..d43e6ef 100644
--- a/src/compiler/translator/RenameFunction.h
+++ b/src/compiler/translator/RenameFunction.h
@@ -7,7 +7,7 @@
#ifndef COMPILER_RENAME_FUNCTION
#define COMPILER_RENAME_FUNCTION
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
//
// Renames a function, including its declaration and any calls to it.
diff --git a/src/compiler/translator/RewriteElseBlocks.h b/src/compiler/translator/RewriteElseBlocks.h
index 39963d6..d87baea 100644
--- a/src/compiler/translator/RewriteElseBlocks.h
+++ b/src/compiler/translator/RewriteElseBlocks.h
@@ -10,7 +10,7 @@
#ifndef COMPILER_REWRITE_ELSE_BLOCKS_H_
#define COMPILER_REWRITE_ELSE_BLOCKS_H_
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
namespace sh
{
diff --git a/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
index c81c5cf..7c6d09c 100644
--- a/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
+++ b/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
@@ -7,7 +7,7 @@
#ifndef COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_
#define COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
class ScalarizeVecAndMatConstructorArgs : public TIntermTraverser
{
diff --git a/src/compiler/translator/SearchSymbol.h b/src/compiler/translator/SearchSymbol.h
index 8ddd3cb..029ac30 100644
--- a/src/compiler/translator/SearchSymbol.h
+++ b/src/compiler/translator/SearchSymbol.h
@@ -9,7 +9,7 @@
#ifndef COMPILER_SEARCHSYMBOL_H_
#define COMPILER_SEARCHSYMBOL_H_
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
#include "compiler/translator/ParseContext.h"
namespace sh
diff --git a/src/compiler/translator/StructureHLSL.h b/src/compiler/translator/StructureHLSL.h
index 63fbaaa..068fa2e 100644
--- a/src/compiler/translator/StructureHLSL.h
+++ b/src/compiler/translator/StructureHLSL.h
@@ -11,7 +11,7 @@
#define TRANSLATOR_STRUCTUREHLSL_H_
#include "compiler/translator/Common.h"
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
#include <set>
diff --git a/src/compiler/translator/SymbolTable.h b/src/compiler/translator/SymbolTable.h
index 6525dee..6b0e0c0 100644
--- a/src/compiler/translator/SymbolTable.h
+++ b/src/compiler/translator/SymbolTable.h
@@ -34,7 +34,7 @@
#include "common/angleutils.h"
#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
// Symbol base class. (Can build functions or variables out of these...)
class TSymbol
diff --git a/src/compiler/translator/UnfoldShortCircuit.h b/src/compiler/translator/UnfoldShortCircuit.h
index 1e416bc..6fd3b45 100644
--- a/src/compiler/translator/UnfoldShortCircuit.h
+++ b/src/compiler/translator/UnfoldShortCircuit.h
@@ -9,7 +9,7 @@
#ifndef COMPILER_UNFOLDSHORTCIRCUIT_H_
#define COMPILER_UNFOLDSHORTCIRCUIT_H_
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
#include "compiler/translator/ParseContext.h"
namespace sh
diff --git a/src/compiler/translator/UnfoldShortCircuitAST.h b/src/compiler/translator/UnfoldShortCircuitAST.h
index 24c14a6..3acaf7e 100644
--- a/src/compiler/translator/UnfoldShortCircuitAST.h
+++ b/src/compiler/translator/UnfoldShortCircuitAST.h
@@ -11,7 +11,7 @@
#define COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_
#include "common/angleutils.h"
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
// This traverser identifies all the short circuit binary nodes that need to
// be replaced, and creates the corresponding replacement nodes. However,
diff --git a/src/compiler/translator/ValidateLimitations.h b/src/compiler/translator/ValidateLimitations.h
index 8c9ebf5..e6e8a96 100644
--- a/src/compiler/translator/ValidateLimitations.h
+++ b/src/compiler/translator/ValidateLimitations.h
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
#include "compiler/translator/LoopInfo.h"
class TInfoSinkBase;
diff --git a/src/compiler/translator/ValidateOutputs.h b/src/compiler/translator/ValidateOutputs.h
index e391ad9..0f808db 100644
--- a/src/compiler/translator/ValidateOutputs.h
+++ b/src/compiler/translator/ValidateOutputs.h
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
#include <set>
diff --git a/src/compiler/translator/VariableInfo.h b/src/compiler/translator/VariableInfo.h
index 916a115..03f7d62 100644
--- a/src/compiler/translator/VariableInfo.h
+++ b/src/compiler/translator/VariableInfo.h
@@ -9,7 +9,7 @@
#include <GLSLANG/ShaderLang.h>
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
// Traverses intermediate tree to collect all attributes, uniforms, varyings.
class CollectVariables : public TIntermTraverser
diff --git a/src/compiler/translator/VersionGLSL.h b/src/compiler/translator/VersionGLSL.h
index de4141d..30f5a13 100644
--- a/src/compiler/translator/VersionGLSL.h
+++ b/src/compiler/translator/VersionGLSL.h
@@ -7,7 +7,7 @@
#ifndef COMPILER_TRANSLATOR_VERSIONGLSL_H_
#define COMPILER_TRANSLATOR_VERSIONGLSL_H_
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
// Traverses the intermediate tree to return the minimum GLSL version
// required to legally access all built-in features used in the shader.
diff --git a/src/compiler/translator/depgraph/DependencyGraph.h b/src/compiler/translator/depgraph/DependencyGraph.h
index 5ea1cbb..bc25fe7 100644
--- a/src/compiler/translator/depgraph/DependencyGraph.h
+++ b/src/compiler/translator/depgraph/DependencyGraph.h
@@ -7,7 +7,7 @@
#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H
#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
#include <set>
#include <stack>
diff --git a/src/compiler/translator/intermOut.cpp b/src/compiler/translator/intermOut.cpp
index a6e7ab4..52a6f51 100644
--- a/src/compiler/translator/intermOut.cpp
+++ b/src/compiler/translator/intermOut.cpp
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
-#include "compiler/translator/localintermediate.h"
+#include "compiler/translator/Intermediate.h"
#include "compiler/translator/SymbolTable.h"
namespace
diff --git a/src/compiler/translator/intermediate.h b/src/compiler/translator/intermediate.h
index 892f284..3b7e7bd 100644
--- a/src/compiler/translator/intermediate.h
+++ b/src/compiler/translator/intermediate.h
@@ -4,768 +4,64 @@
// found in the LICENSE file.
//
-//
-// Definition of the in-memory high-level intermediate representation
-// of shaders. This is a tree that parser creates.
-//
-// Nodes in the tree are defined as a hierarchy of classes derived from
-// TIntermNode. Each is a node in a tree. There is no preset branching factor;
-// each node can have it's own type of list of children.
-//
+#ifndef COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_
+#define COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_
-#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_
-#define COMPILER_TRANSLATOR_INTERMEDIATE_H_
+#include "compiler/translator/IntermNode.h"
-#include "GLSLANG/ShaderLang.h"
-
-#include <algorithm>
-#include <queue>
-
-#include "compiler/translator/Common.h"
-#include "compiler/translator/Types.h"
-#include "compiler/translator/ConstantUnion.h"
-
-//
-// Operators used by the high-level (parse tree) representation.
-//
-enum TOperator
+struct TVectorFields
{
- EOpNull, // if in a node, should only mean a node is still being built
- EOpSequence, // denotes a list of statements, or parameters, etc.
- EOpFunctionCall,
- EOpFunction, // For function definition
- EOpParameters, // an aggregate listing the parameters to a function
-
- EOpDeclaration,
- EOpPrototype,
-
- //
- // Unary operators
- //
-
- EOpNegative,
- EOpLogicalNot,
- EOpVectorLogicalNot,
-
- EOpPostIncrement,
- EOpPostDecrement,
- EOpPreIncrement,
- EOpPreDecrement,
-
- //
- // binary operations
- //
-
- EOpAdd,
- EOpSub,
- EOpMul,
- EOpDiv,
- EOpEqual,
- EOpNotEqual,
- EOpVectorEqual,
- EOpVectorNotEqual,
- EOpLessThan,
- EOpGreaterThan,
- EOpLessThanEqual,
- EOpGreaterThanEqual,
- EOpComma,
-
- EOpVectorTimesScalar,
- EOpVectorTimesMatrix,
- EOpMatrixTimesVector,
- EOpMatrixTimesScalar,
-
- EOpLogicalOr,
- EOpLogicalXor,
- EOpLogicalAnd,
-
- EOpIndexDirect,
- EOpIndexIndirect,
- EOpIndexDirectStruct,
- EOpIndexDirectInterfaceBlock,
-
- EOpVectorSwizzle,
-
- //
- // Built-in functions potentially mapped to operators
- //
-
- EOpRadians,
- EOpDegrees,
- EOpSin,
- EOpCos,
- EOpTan,
- EOpAsin,
- EOpAcos,
- EOpAtan,
-
- EOpPow,
- EOpExp,
- EOpLog,
- EOpExp2,
- EOpLog2,
- EOpSqrt,
- EOpInverseSqrt,
-
- EOpAbs,
- EOpSign,
- EOpFloor,
- EOpCeil,
- EOpFract,
- EOpMod,
- EOpMin,
- EOpMax,
- EOpClamp,
- EOpMix,
- EOpStep,
- EOpSmoothStep,
-
- EOpLength,
- EOpDistance,
- EOpDot,
- EOpCross,
- EOpNormalize,
- EOpFaceForward,
- EOpReflect,
- EOpRefract,
-
- EOpDFdx, // Fragment only, OES_standard_derivatives extension
- EOpDFdy, // Fragment only, OES_standard_derivatives extension
- EOpFwidth, // Fragment only, OES_standard_derivatives extension
-
- EOpMatrixTimesMatrix,
-
- EOpAny,
- EOpAll,
-
- //
- // Branch
- //
-
- EOpKill, // Fragment only
- EOpReturn,
- EOpBreak,
- EOpContinue,
-
- //
- // Constructors
- //
-
- EOpConstructInt,
- EOpConstructUInt,
- EOpConstructBool,
- EOpConstructFloat,
- EOpConstructVec2,
- EOpConstructVec3,
- EOpConstructVec4,
- EOpConstructBVec2,
- EOpConstructBVec3,
- EOpConstructBVec4,
- EOpConstructIVec2,
- EOpConstructIVec3,
- EOpConstructIVec4,
- EOpConstructUVec2,
- EOpConstructUVec3,
- EOpConstructUVec4,
- EOpConstructMat2,
- EOpConstructMat3,
- EOpConstructMat4,
- EOpConstructStruct,
-
- //
- // moves
- //
-
- EOpAssign,
- EOpInitialize,
- EOpAddAssign,
- EOpSubAssign,
- EOpMulAssign,
- EOpVectorTimesMatrixAssign,
- EOpVectorTimesScalarAssign,
- EOpMatrixTimesScalarAssign,
- EOpMatrixTimesMatrixAssign,
- EOpDivAssign
+ int offsets[4];
+ int num;
};
-class TIntermTraverser;
-class TIntermAggregate;
-class TIntermBinary;
-class TIntermUnary;
-class TIntermConstantUnion;
-class TIntermSelection;
-class TIntermTyped;
-class TIntermSymbol;
-class TIntermLoop;
+//
+// Set of helper functions to help parse and build the tree.
+//
class TInfoSink;
-class TIntermRaw;
-
-//
-// Base class for the tree nodes
-//
-class TIntermNode
+class TIntermediate
{
public:
POOL_ALLOCATOR_NEW_DELETE();
- TIntermNode()
- {
- // TODO: Move this to TSourceLoc constructor
- // after getting rid of TPublicType.
- mLine.first_file = mLine.last_file = 0;
- mLine.first_line = mLine.last_line = 0;
- }
- virtual ~TIntermNode() { }
+ TIntermediate(TInfoSink &i)
+ : mInfoSink(i) { }
- const TSourceLoc &getLine() const { return mLine; }
- void setLine(const TSourceLoc &l) { mLine = l; }
+ TIntermSymbol *addSymbol(
+ int id, const TString &, const TType &, const TSourceLoc &);
+ TIntermTyped *addBinaryMath(
+ TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &);
+ TIntermTyped *addAssign(
+ TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &);
+ TIntermTyped *addIndex(
+ TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &);
+ TIntermTyped *addUnaryMath(
+ TOperator op, TIntermNode *child, const TSourceLoc &);
+ TIntermAggregate *growAggregate(
+ TIntermNode *left, TIntermNode *right, const TSourceLoc &);
+ TIntermAggregate *makeAggregate(TIntermNode *node, const TSourceLoc &);
+ TIntermAggregate *setAggregateOperator(TIntermNode *, TOperator, const TSourceLoc &);
+ TIntermNode *addSelection(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &);
+ TIntermTyped *addSelection(
+ TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &);
+ TIntermTyped *addComma(
+ TIntermTyped *left, TIntermTyped *right, const TSourceLoc &);
+ TIntermConstantUnion *addConstantUnion(ConstantUnion *, const TType &, const TSourceLoc &);
+ // TODO(zmo): Get rid of default value.
+ bool parseConstTree(const TSourceLoc &, TIntermNode *, ConstantUnion *,
+ TOperator, TType, bool singleConstantParam = false);
+ TIntermNode *addLoop(TLoopType, TIntermNode *, TIntermTyped *, TIntermTyped *,
+ TIntermNode *, const TSourceLoc &);
+ TIntermBranch *addBranch(TOperator, const TSourceLoc &);
+ TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &);
+ TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &);
+ bool postProcess(TIntermNode *);
+ void remove(TIntermNode *);
+ void outputTree(TIntermNode *);
- virtual void traverse(TIntermTraverser *) = 0;
- virtual TIntermTyped *getAsTyped() { return 0; }
- virtual TIntermConstantUnion *getAsConstantUnion() { return 0; }
- virtual TIntermAggregate *getAsAggregate() { return 0; }
- virtual TIntermBinary *getAsBinaryNode() { return 0; }
- virtual TIntermUnary *getAsUnaryNode() { return 0; }
- virtual TIntermSelection *getAsSelectionNode() { return 0; }
- virtual TIntermSymbol *getAsSymbolNode() { return 0; }
- virtual TIntermLoop *getAsLoopNode() { return 0; }
- virtual TIntermRaw *getAsRawNode() { return 0; }
+ private:
+ void operator=(TIntermediate &); // prevent assignments
- // Replace a child node. Return true if |original| is a child
- // node and it is replaced; otherwise, return false.
- virtual bool replaceChildNode(
- TIntermNode *original, TIntermNode *replacement) = 0;
-
- // For traversing a tree in no particular order, but using
- // heap memory.
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const = 0;
-
- protected:
- TSourceLoc mLine;
+ TInfoSink & mInfoSink;
};
-//
-// This is just to help yacc.
-//
-struct TIntermNodePair
-{
- TIntermNode *node1;
- TIntermNode *node2;
-};
-
-//
-// Intermediate class for nodes that have a type.
-//
-class TIntermTyped : public TIntermNode
-{
- public:
- TIntermTyped(const TType &t) : mType(t) { }
- virtual TIntermTyped *getAsTyped() { return this; }
-
- virtual bool hasSideEffects() const = 0;
-
- void setType(const TType &t) { mType = t; }
- const TType &getType() const { return mType; }
- TType *getTypePointer() { return &mType; }
-
- TBasicType getBasicType() const { return mType.getBasicType(); }
- TQualifier getQualifier() const { return mType.getQualifier(); }
- TPrecision getPrecision() const { return mType.getPrecision(); }
- int getCols() const { return mType.getCols(); }
- int getRows() const { return mType.getRows(); }
- int getNominalSize() const { return mType.getNominalSize(); }
- int getSecondarySize() const { return mType.getSecondarySize(); }
-
- bool isInterfaceBlock() const { return mType.isInterfaceBlock(); }
- bool isMatrix() const { return mType.isMatrix(); }
- bool isArray() const { return mType.isArray(); }
- bool isVector() const { return mType.isVector(); }
- bool isScalar() const { return mType.isScalar(); }
- bool isScalarInt() const { return mType.isScalarInt(); }
- const char *getBasicString() const { return mType.getBasicString(); }
- const char *getQualifierString() const { return mType.getQualifierString(); }
- TString getCompleteString() const { return mType.getCompleteString(); }
-
- int getArraySize() const { return mType.getArraySize(); }
-
- protected:
- TType mType;
-};
-
-//
-// Handle for, do-while, and while loops.
-//
-enum TLoopType
-{
- ELoopFor,
- ELoopWhile,
- ELoopDoWhile
-};
-
-class TIntermLoop : public TIntermNode
-{
- public:
- TIntermLoop(TLoopType type,
- TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
- TIntermNode *body)
- : mType(type),
- mInit(init),
- mCond(cond),
- mExpr(expr),
- mBody(body),
- mUnrollFlag(false) { }
-
- virtual TIntermLoop *getAsLoopNode() { return this; }
- virtual void traverse(TIntermTraverser *);
- virtual bool replaceChildNode(
- TIntermNode *original, TIntermNode *replacement);
-
- TLoopType getType() const { return mType; }
- TIntermNode *getInit() { return mInit; }
- TIntermTyped *getCondition() { return mCond; }
- TIntermTyped *getExpression() { return mExpr; }
- TIntermNode *getBody() { return mBody; }
-
- void setUnrollFlag(bool flag) { mUnrollFlag = flag; }
- bool getUnrollFlag() const { return mUnrollFlag; }
-
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
-
- protected:
- TLoopType mType;
- TIntermNode *mInit; // for-loop initialization
- TIntermTyped *mCond; // loop exit condition
- TIntermTyped *mExpr; // for-loop expression
- TIntermNode *mBody; // loop body
-
- bool mUnrollFlag; // Whether the loop should be unrolled or not.
-};
-
-//
-// Handle break, continue, return, and kill.
-//
-class TIntermBranch : public TIntermNode
-{
- public:
- TIntermBranch(TOperator op, TIntermTyped *e)
- : mFlowOp(op),
- mExpression(e) { }
-
- virtual void traverse(TIntermTraverser *);
- virtual bool replaceChildNode(
- TIntermNode *original, TIntermNode *replacement);
-
- TOperator getFlowOp() { return mFlowOp; }
- TIntermTyped* getExpression() { return mExpression; }
-
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
-
-protected:
- TOperator mFlowOp;
- TIntermTyped *mExpression; // non-zero except for "return exp;" statements
-};
-
-//
-// Nodes that correspond to symbols or constants in the source code.
-//
-class TIntermSymbol : public TIntermTyped
-{
- public:
- // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym.
- // If sym comes from per process globalpoolallocator, then it causes increased memory usage
- // per compile it is essential to use "symbol = sym" to assign to symbol
- TIntermSymbol(int id, const TString &symbol, const TType &type)
- : TIntermTyped(type),
- mId(id)
- {
- mSymbol = symbol;
- }
-
- virtual bool hasSideEffects() const { return false; }
-
- int getId() const { return mId; }
- const TString &getSymbol() const { return mSymbol; }
-
- void setId(int newId) { mId = newId; }
-
- virtual void traverse(TIntermTraverser *);
- virtual TIntermSymbol *getAsSymbolNode() { return this; }
- virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
-
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
-
- protected:
- int mId;
- TString mSymbol;
-};
-
-// A Raw node stores raw code, that the translator will insert verbatim
-// into the output stream. Useful for transformation operations that make
-// complex code that might not fit naturally into the GLSL model.
-class TIntermRaw : public TIntermTyped
-{
- public:
- TIntermRaw(const TType &type, const TString &rawText)
- : TIntermTyped(type),
- mRawText(rawText) { }
-
- virtual bool hasSideEffects() const { return false; }
-
- TString getRawText() const { return mRawText; }
-
- virtual void traverse(TIntermTraverser *);
-
- virtual TIntermRaw *getAsRawNode() { return this; }
- virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
-
- protected:
- TString mRawText;
-};
-
-class TIntermConstantUnion : public TIntermTyped
-{
- public:
- TIntermConstantUnion(ConstantUnion *unionPointer, const TType &type)
- : TIntermTyped(type),
- mUnionArrayPointer(unionPointer) { }
-
- virtual bool hasSideEffects() const { return false; }
-
- ConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; }
-
- int getIConst(size_t index) const
- {
- return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0;
- }
- unsigned int getUConst(size_t index) const
- {
- return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0;
- }
- float getFConst(size_t index) const
- {
- return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f;
- }
- bool getBConst(size_t index) const
- {
- return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false;
- }
-
- virtual TIntermConstantUnion *getAsConstantUnion() { return this; }
- virtual void traverse(TIntermTraverser *);
- virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
-
- TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &);
-
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
-
- protected:
- ConstantUnion *mUnionArrayPointer;
-};
-
-//
-// Intermediate class for node types that hold operators.
-//
-class TIntermOperator : public TIntermTyped
-{
- public:
- TOperator getOp() const { return mOp; }
- void setOp(TOperator op) { mOp = op; }
-
- bool isAssignment() const;
- bool isConstructor() const;
-
- virtual bool hasSideEffects() const { return isAssignment(); }
-
- protected:
- TIntermOperator(TOperator op)
- : TIntermTyped(TType(EbtFloat, EbpUndefined)),
- mOp(op) {}
- TIntermOperator(TOperator op, const TType &type)
- : TIntermTyped(type),
- mOp(op) {}
-
- TOperator mOp;
-};
-
-//
-// Nodes for all the basic binary math operators.
-//
-class TIntermBinary : public TIntermOperator
-{
- public:
- TIntermBinary(TOperator op)
- : TIntermOperator(op),
- mAddIndexClamp(false) {}
-
- virtual TIntermBinary *getAsBinaryNode() { return this; }
- virtual void traverse(TIntermTraverser *);
- virtual bool replaceChildNode(
- TIntermNode *original, TIntermNode *replacement);
-
- virtual bool hasSideEffects() const
- {
- return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects();
- }
-
- void setLeft(TIntermTyped *node) { mLeft = node; }
- void setRight(TIntermTyped *node) { mRight = node; }
- TIntermTyped *getLeft() const { return mLeft; }
- TIntermTyped *getRight() const { return mRight; }
- bool promote(TInfoSink &);
-
- void setAddIndexClamp() { mAddIndexClamp = true; }
- bool getAddIndexClamp() { return mAddIndexClamp; }
-
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
-
- protected:
- TIntermTyped* mLeft;
- TIntermTyped* mRight;
-
- // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
- bool mAddIndexClamp;
-};
-
-//
-// Nodes for unary math operators.
-//
-class TIntermUnary : public TIntermOperator
-{
- public:
- TIntermUnary(TOperator op, const TType &type)
- : TIntermOperator(op, type),
- mOperand(NULL),
- mUseEmulatedFunction(false) {}
- TIntermUnary(TOperator op)
- : TIntermOperator(op),
- mOperand(NULL),
- mUseEmulatedFunction(false) {}
-
- virtual void traverse(TIntermTraverser *);
- virtual TIntermUnary *getAsUnaryNode() { return this; }
- virtual bool replaceChildNode(
- TIntermNode *original, TIntermNode *replacement);
-
- virtual bool hasSideEffects() const
- {
- return isAssignment() || mOperand->hasSideEffects();
- }
-
- void setOperand(TIntermTyped *operand) { mOperand = operand; }
- TIntermTyped *getOperand() { return mOperand; }
- bool promote(TInfoSink &);
-
- void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
- bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
-
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
-
- protected:
- TIntermTyped *mOperand;
-
- // If set to true, replace the built-in function call with an emulated one
- // to work around driver bugs.
- bool mUseEmulatedFunction;
-};
-
-typedef TVector<TIntermNode *> TIntermSequence;
-typedef TVector<int> TQualifierList;
-
-//
-// Nodes that operate on an arbitrary sized set of children.
-//
-class TIntermAggregate : public TIntermOperator
-{
- public:
- TIntermAggregate()
- : TIntermOperator(EOpNull),
- mUserDefined(false),
- mUseEmulatedFunction(false) { }
- TIntermAggregate(TOperator op)
- : TIntermOperator(op),
- mUseEmulatedFunction(false) { }
- ~TIntermAggregate() { }
-
- virtual TIntermAggregate *getAsAggregate() { return this; }
- virtual void traverse(TIntermTraverser *);
- virtual bool replaceChildNode(
- TIntermNode *original, TIntermNode *replacement);
-
- // Conservatively assume function calls and other aggregate operators have side-effects
- virtual bool hasSideEffects() const { return true; }
-
- TIntermSequence *getSequence() { return &mSequence; }
-
- void setName(const TString &name) { mName = name; }
- const TString &getName() const { return mName; }
-
- void setUserDefined() { mUserDefined = true; }
- bool isUserDefined() const { return mUserDefined; }
-
- void setOptimize(bool optimize) { mOptimize = optimize; }
- bool getOptimize() const { return mOptimize; }
- void setDebug(bool debug) { mDebug = debug; }
- bool getDebug() const { return mDebug; }
-
- void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
- bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
-
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
-
- protected:
- TIntermAggregate(const TIntermAggregate &); // disallow copy constructor
- TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator
- TIntermSequence mSequence;
- TString mName;
- bool mUserDefined; // used for user defined function names
-
- bool mOptimize;
- bool mDebug;
-
- // If set to true, replace the built-in function call with an emulated one
- // to work around driver bugs.
- bool mUseEmulatedFunction;
-};
-
-//
-// For if tests. Simplified since there is no switch statement.
-//
-class TIntermSelection : public TIntermTyped
-{
- public:
- TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB)
- : TIntermTyped(TType(EbtVoid, EbpUndefined)),
- mCondition(cond),
- mTrueBlock(trueB),
- mFalseBlock(falseB) {}
- TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB,
- const TType &type)
- : TIntermTyped(type),
- mCondition(cond),
- mTrueBlock(trueB),
- mFalseBlock(falseB) {}
-
- virtual void traverse(TIntermTraverser *);
- virtual bool replaceChildNode(
- TIntermNode *original, TIntermNode *replacement);
-
- // Conservatively assume selections have side-effects
- virtual bool hasSideEffects() const { return true; }
-
- bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
- TIntermNode *getCondition() const { return mCondition; }
- TIntermNode *getTrueBlock() const { return mTrueBlock; }
- TIntermNode *getFalseBlock() const { return mFalseBlock; }
- TIntermSelection *getAsSelectionNode() { return this; }
-
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
-
-protected:
- TIntermTyped *mCondition;
- TIntermNode *mTrueBlock;
- TIntermNode *mFalseBlock;
-};
-
-enum Visit
-{
- PreVisit,
- InVisit,
- PostVisit
-};
-
-//
-// For traversing the tree. User should derive from this,
-// put their traversal specific data in it, and then pass
-// it to a Traverse method.
-//
-// When using this, just fill in the methods for nodes you want visited.
-// Return false from a pre-visit to skip visiting that node's subtree.
-//
-class TIntermTraverser
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- // TODO(zmo): remove default values.
- TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false,
- bool rightToLeft = false)
- : preVisit(preVisit),
- inVisit(inVisit),
- postVisit(postVisit),
- rightToLeft(rightToLeft),
- mDepth(0),
- mMaxDepth(0) {}
- virtual ~TIntermTraverser() {}
-
- virtual void visitSymbol(TIntermSymbol *) {}
- virtual void visitRaw(TIntermRaw *) {}
- virtual void visitConstantUnion(TIntermConstantUnion *) {}
- virtual bool visitBinary(Visit, TIntermBinary *) { return true; }
- virtual bool visitUnary(Visit, TIntermUnary *) { return true; }
- virtual bool visitSelection(Visit, TIntermSelection *) { return true; }
- virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; }
- virtual bool visitLoop(Visit, TIntermLoop *) { return true; }
- virtual bool visitBranch(Visit, TIntermBranch *) { return true; }
-
- int getMaxDepth() const { return mMaxDepth; }
-
- void incrementDepth(TIntermNode *current)
- {
- mDepth++;
- mMaxDepth = std::max(mMaxDepth, mDepth);
- mPath.push_back(current);
- }
-
- void decrementDepth()
- {
- mDepth--;
- mPath.pop_back();
- }
-
- TIntermNode *getParentNode()
- {
- return mPath.size() == 0 ? NULL : mPath.back();
- }
-
- // Return the original name if hash function pointer is NULL;
- // otherwise return the hashed name.
- static TString hash(const TString& name, ShHashFunction64 hashFunction);
-
- const bool preVisit;
- const bool inVisit;
- const bool postVisit;
- const bool rightToLeft;
-
- protected:
- int mDepth;
- int mMaxDepth;
-
- // All the nodes from root to the current node's parent during traversing.
- TVector<TIntermNode *> mPath;
-};
-
-//
-// For traversing the tree, and computing max depth.
-// Takes a maximum depth limit to prevent stack overflow.
-//
-class TMaxDepthTraverser : public TIntermTraverser
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- TMaxDepthTraverser(int depthLimit)
- : TIntermTraverser(true, true, false, false),
- mDepthLimit(depthLimit) { }
-
- virtual bool visitBinary(Visit, TIntermBinary *) { return depthCheck(); }
- virtual bool visitUnary(Visit, TIntermUnary *) { return depthCheck(); }
- virtual bool visitSelection(Visit, TIntermSelection *) { return depthCheck(); }
- virtual bool visitAggregate(Visit, TIntermAggregate *) { return depthCheck(); }
- virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); }
- virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); }
-
-protected:
- bool depthCheck() const { return mMaxDepth < mDepthLimit; }
-
- int mDepthLimit;
-};
-
-#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_
+#endif // COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_
diff --git a/src/compiler/translator/localintermediate.h b/src/compiler/translator/localintermediate.h
deleted file mode 100644
index 0809bbd..0000000
--- a/src/compiler/translator/localintermediate.h
+++ /dev/null
@@ -1,67 +0,0 @@
-//
-// Copyright (c) 2002-2014 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.
-//
-
-#ifndef COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_
-#define COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_
-
-#include "compiler/translator/intermediate.h"
-
-struct TVectorFields
-{
- int offsets[4];
- int num;
-};
-
-//
-// Set of helper functions to help parse and build the tree.
-//
-class TInfoSink;
-class TIntermediate
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- TIntermediate(TInfoSink &i)
- : mInfoSink(i) { }
-
- TIntermSymbol *addSymbol(
- int id, const TString &, const TType &, const TSourceLoc &);
- TIntermTyped *addBinaryMath(
- TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &);
- TIntermTyped *addAssign(
- TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &);
- TIntermTyped *addIndex(
- TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &);
- TIntermTyped *addUnaryMath(
- TOperator op, TIntermNode *child, const TSourceLoc &);
- TIntermAggregate *growAggregate(
- TIntermNode *left, TIntermNode *right, const TSourceLoc &);
- TIntermAggregate *makeAggregate(TIntermNode *node, const TSourceLoc &);
- TIntermAggregate *setAggregateOperator(TIntermNode *, TOperator, const TSourceLoc &);
- TIntermNode *addSelection(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &);
- TIntermTyped *addSelection(
- TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &);
- TIntermTyped *addComma(
- TIntermTyped *left, TIntermTyped *right, const TSourceLoc &);
- TIntermConstantUnion *addConstantUnion(ConstantUnion *, const TType &, const TSourceLoc &);
- // TODO(zmo): Get rid of default value.
- bool parseConstTree(const TSourceLoc &, TIntermNode *, ConstantUnion *,
- TOperator, TType, bool singleConstantParam = false);
- TIntermNode *addLoop(TLoopType, TIntermNode *, TIntermTyped *, TIntermTyped *,
- TIntermNode *, const TSourceLoc &);
- TIntermBranch *addBranch(TOperator, const TSourceLoc &);
- TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &);
- TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &);
- bool postProcess(TIntermNode *);
- void remove(TIntermNode *);
- void outputTree(TIntermNode *);
-
- private:
- void operator=(TIntermediate &); // prevent assignments
-
- TInfoSink & mInfoSink;
-};
-
-#endif // COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_
diff --git a/src/compiler/translator/timing/RestrictFragmentShaderTiming.h b/src/compiler/translator/timing/RestrictFragmentShaderTiming.h
index e77d8c2..80d5f7f 100644
--- a/src/compiler/translator/timing/RestrictFragmentShaderTiming.h
+++ b/src/compiler/translator/timing/RestrictFragmentShaderTiming.h
@@ -7,7 +7,7 @@
#ifndef COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_
#define COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
#include "compiler/translator/depgraph/DependencyGraph.h"
class TInfoSinkBase;
diff --git a/src/compiler/translator/timing/RestrictVertexShaderTiming.h b/src/compiler/translator/timing/RestrictVertexShaderTiming.h
index d461fbd..a626356 100644
--- a/src/compiler/translator/timing/RestrictVertexShaderTiming.h
+++ b/src/compiler/translator/timing/RestrictVertexShaderTiming.h
@@ -7,7 +7,7 @@
#ifndef COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_
#define COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
#include "compiler/translator/InfoSink.h"
class TInfoSinkBase;
diff --git a/src/third_party/compiler/ArrayBoundsClamper.h b/src/third_party/compiler/ArrayBoundsClamper.h
index 7d06a6c..30bb7e3 100644
--- a/src/third_party/compiler/ArrayBoundsClamper.h
+++ b/src/third_party/compiler/ArrayBoundsClamper.h
@@ -27,7 +27,7 @@
#define THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_
#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/intermediate.h"
+#include "compiler/translator/IntermNode.h"
class ArrayBoundsClamper {
public: