Add a GetVariableInfo helper method.

This method replaces the similar logic in storing uniforms,
varyings, and interface blocks when collecting variable info.
We can also re-use this method for both GLSL and HLSL programs.

BUG=angle:466

Change-Id: Ie6c13abe0f09f38b2f9b36e117caae4833eaccbf
Reviewed-on: https://chromium-review.googlesource.com/206566
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Nicolas Capens <capn@chromium.org>
diff --git a/src/compiler/translator/util.cpp b/src/compiler/translator/util.cpp
index 2b6e0ee..b9fc0b4 100644
--- a/src/compiler/translator/util.cpp
+++ b/src/compiler/translator/util.cpp
@@ -10,6 +10,7 @@
 
 #include "compiler/preprocessor/numeric_lex.h"
 #include "common/shadervars.h"
+#include "common/utilities.h"
 
 bool atof_clamp(const char *str, float *value)
 {
@@ -279,4 +280,66 @@
     }
 }
 
+template <typename VarT>
+void GetVariableTraverser<VarT>::traverse(const TType &type, const TString &name)
+{
+    const TStructure *structure = type.getStruct();
+
+    VarT variable;
+    variable.name = name.c_str();
+    variable.arraySize = static_cast<unsigned int>(type.getArraySize());
+
+    if (!structure)
+    {
+        variable.type = GLVariableType(type);
+        variable.precision = GLVariablePrecision(type);
+    }
+    else
+    {
+        variable.type = GL_STRUCT_ANGLEX;
+
+        mOutputStack.push(&variable.fields);
+
+        const TFieldList &fields = structure->fields();
+
+        for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
+        {
+            TField *field = fields[fieldIndex];
+            traverse(*field->type(), field->name());
+        }
+
+        mOutputStack.pop();
+    }
+
+    visitVariable(&variable);
+
+    ASSERT(!mOutputStack.empty());
+    mOutputStack.top()->push_back(variable);
+}
+
+template <typename VarT>
+GetVariableTraverser<VarT>::GetVariableTraverser(std::vector<VarT> *output)
+{
+    ASSERT(output);
+    mOutputStack.push(output);
+}
+
+template class GetVariableTraverser<Uniform>;
+template class GetVariableTraverser<Varying>;
+template class GetVariableTraverser<InterfaceBlockField>;
+
+GetInterfaceBlockFieldTraverser::GetInterfaceBlockFieldTraverser(std::vector<InterfaceBlockField> *output, bool isRowMajorMatrix)
+    : GetVariableTraverser(output),
+      mIsRowMajorMatrix(isRowMajorMatrix)
+{
+}
+
+void GetInterfaceBlockFieldTraverser::visitVariable(InterfaceBlockField *newField)
+{
+    if (gl::IsMatrixType(newField->type))
+    {
+        newField->isRowMajorMatrix = mIsRowMajorMatrix;
+    }
+}
+
 }