Fix spec const construtor for matrix and vector

Fix issue: #237

1. The code generated for matrix constructor should 1) build column
vectors first, 2) build matrix with the vectors.

2. When there is only one scalar type constituent in vector's
constructor, we should populate the constituent to fill all the slots in
the vector. As for matrix, the single constituent should be populated to
the diagonal positions (top-left to bottom-right diagonal).

remove createSpvConstantFromConstSubTree()
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 39f3b8b..9d4dc59 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -151,7 +151,6 @@
     void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value);
     spv::Id createSpvConstant(const glslang::TIntermTyped&);
     spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
-    spv::Id createSpvConstantFromConstSubTree(glslang::TIntermTyped* subTree);
     bool isTrivialLeaf(const glslang::TIntermTyped* node);
     bool isTrivial(const glslang::TIntermTyped* node);
     spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
@@ -1113,6 +1112,10 @@
 
 bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate* node)
 {
+    SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
+    if (node->getType().getQualifier().isSpecConstant())
+        spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
+
     spv::Id result = spv::NoResult;
 
     // try texturing
@@ -3814,7 +3817,11 @@
     // Its initializer should either be a sub tree with constant nodes, or a constant union array.
     if (auto* sn = node.getAsSymbolNode()) {
         if (auto* sub_tree = sn->getConstSubtree()) {
-            return createSpvConstantFromConstSubTree(sub_tree);
+            // Traverse the constant constructor sub tree like generating normal run-time instructions.
+            // During the AST traversal, if the node is marked as 'specConstant', SpecConstantOpModeGuard
+            // will set the builder into spec constant op instruction generating mode.
+            sub_tree->traverse(this);
+            return accessChainLoad(sub_tree->getType());
         } else if (auto* const_union_array = &sn->getConstArray()){
             int nextConst = 0;
             return createSpvConstantFromConstUnionArray(sn->getType(), *const_union_array, nextConst, true);
@@ -3910,68 +3917,6 @@
     return builder.makeCompositeConstant(typeId, spvConsts);
 }
 
-// Create constant ID from const initializer sub tree.
-spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree(
-    glslang::TIntermTyped* subTree)
-{
-    const glslang::TType& glslangType = subTree->getType();
-    spv::Id typeId = convertGlslangToSpvType(glslangType);
-    bool is_spec_const = subTree->getType().getQualifier().isSpecConstant();
-    if (const glslang::TIntermAggregate* an = subTree->getAsAggregate()) {
-        // Aggregate node, we should generate OpConstantComposite or
-        // OpSpecConstantComposite instruction.
-
-        std::vector<spv::Id> const_constituents;
-        for (auto NI = an->getSequence().begin(); NI != an->getSequence().end();
-             NI++) {
-            const_constituents.push_back(
-                createSpvConstantFromConstSubTree((*NI)->getAsTyped()));
-        }
-        // Note that constructors are aggregate nodes, so expressions like:
-        // float x = float(y) will become an aggregate node. If 'x' is declared
-        // as a constant, the aggregate node representing 'float(y)' will be
-        // processed here.
-        if (builder.isVectorType(typeId) || builder.isMatrixType(typeId) ||
-            builder.isAggregateType(typeId)) {
-            return builder.makeCompositeConstant(typeId, const_constituents, is_spec_const);
-        } else {
-            assert(builder.isScalarType(typeId) && const_constituents.size() == 1);
-            return const_constituents.front();
-        }
-
-    } else if (glslang::TIntermBinary* bn = subTree->getAsBinaryNode()) {
-        // Binary operation node, we should generate OpSpecConstantOp <binary op>
-        // This case should only happen when Specialization Constants are involved.
-        bn->traverse(this);
-        return accessChainLoad(bn->getType());
-
-    } else if (glslang::TIntermUnary* un = subTree->getAsUnaryNode()) {
-        // Unary operation node, similar to binary operation node, should only
-        // happen when specialization constants are involved.
-        un->traverse(this);
-        return accessChainLoad(un->getType());
-
-    } else if (const glslang::TIntermConstantUnion* cn = subTree->getAsConstantUnion()) {
-        // ConstantUnion node, should redirect to
-        // createSpvConstantFromConstUnionArray
-        int nextConst = 0;
-        return createSpvConstantFromConstUnionArray(
-            glslangType, cn->getConstArray(), nextConst, is_spec_const);
-
-    } else if (const glslang::TIntermSymbol* sn = subTree->getAsSymbolNode()) {
-        // Symbol node. Call getSymbolId(). This should cover both cases 1) the
-        // symbol has already been assigned an ID, 2) need a new ID for this
-        // symbol.
-        return getSymbolId(sn);
-
-    } else {
-        spv::MissingFunctionality(
-            "createSpvConstantFromConstSubTree() not covered TIntermTyped* const "
-            "initializer subtree.");
-        return spv::NoResult;
-    }
-}
-
 // Return true if the node is a constant or symbol whose reading has no
 // non-trivial observable cost or effect.
 bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node)
diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp
index 7896deb..5768196 100644
--- a/SPIRV/SpvBuilder.cpp
+++ b/SPIRV/SpvBuilder.cpp
@@ -645,6 +645,21 @@
     }
 }
 
+// Return true if consuming 'opcode' means consuming a specialization constant.
+bool Builder::isSpecConstantOpCode(Op opcode) const
+{
+    switch (opcode) {
+    case OpSpecConstantTrue:
+    case OpSpecConstantFalse:
+    case OpSpecConstant:
+    case OpSpecConstantComposite:
+    case OpSpecConstantOp:
+        return true;
+    default:
+        return false;
+    }
+}
+
 Id Builder::makeBoolConstant(bool b, bool specConstant)
 {
     Id typeId = makeBoolType();
@@ -1345,13 +1360,9 @@
     Instruction* smear = nullptr;
     if (generatingOpCodeForSpecConst) {
         auto members = std::vector<spv::Id>(numComponents, scalar);
-        // 'scalar' can not be spec constant here. All spec constant involved
-        // promotion is done in createSpvConstantFromConstUnionArray().  This
-        // 'if' branch is only accessed when 'scalar' is used in the def-chain
-        // of other vector type spec constants. In such cases, all the
-        // instructions needed to promote 'scalar' to a vector type constants
-        // should be added at module level.
-        auto result_id = makeCompositeConstant(vectorType, members, false);
+        // "generatingOpCodeForSpecConst == true" does not mean the generated vector
+        // is a spec constant vector. It depends on the scalar.
+        auto result_id = makeCompositeConstant(vectorType, members, isSpecConstant(scalar));
         smear = module.getInstruction(result_id);
     } else {
         smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct);
@@ -1714,6 +1725,10 @@
 {
     assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size()));
 
+    if (generatingOpCodeForSpecConst) {
+        return makeCompositeConstant(typeId, constituents, true);
+    }
+
     Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct);
     for (int c = 0; c < (int)constituents.size(); ++c)
         op->addIdOperand(constituents[c]);
diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h
index 62f6775..661bb11 100755
--- a/SPIRV/SpvBuilder.h
+++ b/SPIRV/SpvBuilder.h
@@ -147,8 +147,10 @@
     bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
 
     bool isConstantOpCode(Op opcode) const;
+    bool isSpecConstantOpCode(Op opcode) const;
     bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
     bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
+    bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); }
     unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
     StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }