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: