Misc. constant-folding fixes: Check % for 0, mat(mat) constructor, index range checki...
authorJohn Kessenich <cepheus@frii.com>
Fri, 8 Nov 2013 21:47:56 +0000 (21:47 +0000)
committerJohn Kessenich <cepheus@frii.com>
Fri, 8 Nov 2013 21:47:56 +0000 (21:47 +0000)
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23973 e7fa87d3-cd2b-0410-9028-fcbf551c1848

Test/baseResults/array.frag.out
Test/baseResults/array100.frag.out
Test/baseResults/constFold.frag.out
Test/baseResults/matrixError.vert.out
Test/constFold.frag
glslang/MachineIndependent/Constant.cpp
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.h
glslang/MachineIndependent/parseConst.cpp

index dd3fab1..e2046f8 100644 (file)
@@ -6,12 +6,12 @@ ERROR: 0:31: 'assign' :  cannot convert from '4-element array of float' to 'unsi
 ERROR: 0:33: 'foo' : no matching overloaded function found \r
 ERROR: 0:42: '[' :  array index out of range '5'\r
 ERROR: 0:45: '[' :  array index out of range '1000'\r
-ERROR: 0:46: '[' :  array index out of range '-1'\r
-ERROR: 0:52: '[' :  array index '2' out of range\r
+ERROR: 0:46: '[' :  index out of range '-1'\r
+ERROR: 0:52: '[' :  array index out of range '2'\r
 ERROR: 0:54: 'const' : non-matching or non-convertible constant type for const initializer \r
 ERROR: 0:56: '=' :  cannot convert from 'const 2-element array of int' to '3-element array of int'\r
 ERROR: 0:57: '[]' : scalar integer expression required \r
-ERROR: 0:57: '[' :  array index out of range '-858993459'\r
+ERROR: 0:57: '[' :  index out of range '-858993459'\r
 ERROR: 0:58: '[]' : scalar integer expression required \r
 ERROR: 14 compilation errors.  No code generated.\r
 \r
@@ -157,7 +157,7 @@ ERROR: node is still EOpNull!
 0:52      add second child into first child (int)\r
 0:52        'sum' (int)\r
 0:52        Constant:\r
-0:52          3 (const int)\r
+0:52          2 (const int)\r
 0:55      Sequence\r
 0:55        move second child to first child (2-element array of int)\r
 0:55          'ica' (2-element array of int)\r
index 400b097..a7e0c5b 100644 (file)
@@ -14,7 +14,7 @@ ERROR: 0:31: 'arrayed constructor' : not supported for this version or the enabl
 ERROR: 0:31: 'array comparison' : not supported for this version or the enabled extensions \r
 ERROR: 0:35: '[' :  array index out of range '5'\r
 ERROR: 0:38: '[' :  array index out of range '1000'\r
-ERROR: 0:39: '[' :  array index out of range '-1'\r
+ERROR: 0:39: '[' :  index out of range '-1'\r
 ERROR: 17 compilation errors.  No code generated.\r
 \r
 ERROR: node is still EOpNull!\r
index e70ee55..ba751b3 100644 (file)
@@ -1,5 +1,13 @@
 Warning, version 430 is not yet complete; some version-specific features are present, but many are missing.\r
-0:? Sequence\r
+ERROR: 0:109: '[' :  index out of range '-1'\r
+ERROR: 0:110: '[' :  vector index out of range '4'\r
+ERROR: 0:111: '[' :  index out of range '-2'\r
+ERROR: 0:112: '[' :  index out of range '-1'\r
+ERROR: 0:113: '[' :  vector index out of range '3'\r
+ERROR: 0:114: '[' :  matrix index out of range '3'\r
+ERROR: 6 compilation errors.  No code generated.\r
+\r
+ERROR: node is still EOpNull!\r
 0:28  Function Definition: main( (void)\r
 0:28    Function Parameters: \r
 0:30    Sequence\r
@@ -163,6 +171,51 @@ Warning, version 430 is not yet complete; some version-specific features are pre
 0:81            0 (const int)\r
 0:81        Constant:\r
 0:81          7.000000\r
+0:82      Constant:\r
+0:82        2 (const int)\r
+0:83      Constant:\r
+0:83        2147483647 (const int)\r
+0:84      Constant:\r
+0:84        1.#INF00\r
+0:88      Constant:\r
+0:88        2 (const uint)\r
+0:88        3 (const uint)\r
+0:89      Constant:\r
+0:89        0 (const uint)\r
+0:90      Constant:\r
+0:90        6 (const uint)\r
+0:90        7 (const uint)\r
+0:103  Function Definition: foo2( (void)\r
+0:103    Function Parameters: \r
+0:105    Sequence\r
+0:105      direct index (float)\r
+0:105        'a1' (1-element array of float)\r
+0:105        Constant:\r
+0:105          0 (const int)\r
+0:106      direct index (float)\r
+0:106        'a2' (2-element array of float)\r
+0:106        Constant:\r
+0:106          0 (const int)\r
+0:107      direct index (float)\r
+0:107        'a3' (4-element array of float)\r
+0:107        Constant:\r
+0:107          0 (const int)\r
+0:108      direct index (float)\r
+0:108        'a4' (2-element array of float)\r
+0:108        Constant:\r
+0:108          0 (const int)\r
+0:109      Constant:\r
+0:109        1.000000\r
+0:110      Constant:\r
+0:110        5.000000\r
+0:111      Constant:\r
+0:111        2.000000\r
+0:112      Constant:\r
+0:112        3.000000\r
+0:113      Constant:\r
+0:113        0.000000\r
+0:114      Constant:\r
+0:114        0.000000\r
 0:?   Linker Objects\r
 0:?     'a' (const int)\r
 0:?       1 (const int)\r
@@ -209,4 +262,32 @@ Warning, version 430 is not yet complete; some version-specific features are pre
 0:?       6.000000\r
 0:?       7.000000\r
 0:?       8.000000\r
+0:?     'm2' (const 2X2 matrix of float)\r
+0:?       2.000000\r
+0:?       3.000000\r
+0:?       4.000000\r
+0:?       5.000000\r
+0:?     'm3' (const 3X3 matrix of float)\r
+0:?       2.000000\r
+0:?       3.000000\r
+0:?       0.000000\r
+0:?       4.000000\r
+0:?       5.000000\r
+0:?       0.000000\r
+0:?       0.000000\r
+0:?       0.000000\r
+0:?       1.000000\r
+0:?     'mc' (const int)\r
+0:?       1 (const int)\r
+0:?     'a1' (1-element array of float)\r
+0:?     'a2' (2-element array of float)\r
+0:?     'a3' (4-element array of float)\r
+0:?     'v2' (const 2-component vector of float)\r
+0:?       1.000000\r
+0:?       2.000000\r
+0:?     'v3' (const 3-component vector of float)\r
+0:?       3.000000\r
+0:?       4.000000\r
+0:?       5.000000\r
+0:?     'a4' (2-element array of float)\r
 \r
index 70bdae8..1ac11f1 100644 (file)
@@ -3,8 +3,8 @@ ERROR: 0:7: 'const' : non-matching or non-convertible constant type for const in
 ERROR: 0:17: 'assign' :  cannot convert from '2-component vector of float' to '3-component vector of float'\r
 ERROR: 0:18: 'assign' :  cannot convert from '2-component vector of float' to '3-component vector of float'\r
 ERROR: 0:19: '.' : field selection not allowed on matrix \r
-ERROR: 0:21: '[' :  index out of range '2'\r
-ERROR: 0:21: '[' :  index out of range '4'\r
+ERROR: 0:21: '[' :  matrix index out of range '2'\r
+ERROR: 0:21: '[' :  vector index out of range '4'\r
 ERROR: 7 compilation errors.  No code generated.\r
 \r
 ERROR: node is still EOpNull!\r
index e5a007d..824d630 100644 (file)
@@ -79,4 +79,37 @@ void foo()
 {
     float a[s.iv2.y];  // 3 element array
     a[0] = s.m[1].z;     // 7.0
+    b % 0;  // int
+    b / 0;
+    e / 0;
+    const uint ua = 5;
+    const uvec2 ub = uvec2(6, 7);
+    const uint uc = 8;
+    ub % 4u;
+    0u % uc;
+    ub % 0u;
 }
+
+const mat2 m2 = mat2(2, 3, 4, 5);
+const mat3 m3 = mat3(m2);
+const int mc = int(m3[2][2]);
+float a1[mc];
+float a2[int(m3[2][1]) + 2];  // size 2
+float a3[int(m3[1][0])];  // size 4
+const vec2 v2 = vec2(1, 2);
+const vec3 v3 = vec3(3, 4, 5);
+float a4[uint(mat3(v2, v3, v2, v2)[2][2])];  // size 2
+
+void foo2()
+{
+    a1[0]; // array size 1
+    a2[0]; // array size 2
+    a3[0]; // array size 4
+    a4[0]; // array size 2
+    v2[-1]; // ERROR
+    v3[4];  // ERROR
+    m3[0][-2];  // ERROR
+    m2[-1][1];  // ERROR
+    m3[1][3];   // ERROR
+    m3[3][1];   // ERROR
+}
\ No newline at end of file
index 67b90c8..b5c2b4f 100644 (file)
@@ -166,7 +166,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
 
             case EbtInt:
                 if (rightUnionArray[i] == 0) {
-                    newConstArray[i].setIConst(0xEFFFFFFF);
+                    newConstArray[i].setIConst(0x7FFFFFFF);
                 } else
                     newConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
                 break;
@@ -207,8 +207,12 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
         break;
 
     case EOpMod:
-        for (int i = 0; i < objectSize; i++)
-            newConstArray[i] = unionArray[i] % rightUnionArray[i];
+        for (int i = 0; i < objectSize; i++) {
+            if (rightUnionArray[i] == 0)
+                newConstArray[i] = unionArray[i];
+            else
+                newConstArray[i] = unionArray[i] % rightUnionArray[i];
+        }
         break;
 
     case EOpRightShift:
index 565abba..9adb2eb 100644 (file)
@@ -437,6 +437,12 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
 {
     TIntermTyped* result = 0;
 
+    int indexValue = 0;
+    if (index->getQualifier().storage == EvqConst) {
+        indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst();
+        checkIndex(loc, base->getType(), indexValue);
+    }
+
     variableCheck(base);
     if (! base->isArray() && ! base->isMatrix() && ! base->isVector()) {
         if (base->getAsSymbolNode())
@@ -446,31 +452,22 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
     } else if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst) {
         if (base->isArray()) {
             // constant folding for arrays
-            result = addConstArrayNode(index->getAsConstantUnion()->getConstArray()[0].getIConst(), base, loc);
+            result = addConstArrayNode(loc, indexValue, base);
         } else if (base->isVector()) {
             // constant folding for vectors
-            TVectorFields fields;
+            TVectorFields fields; // need to do it this way because v.xy sends fields integer array
             fields.num = 1;
-            fields.offsets[0] = index->getAsConstantUnion()->getConstArray()[0].getIConst(); // need to do it this way because v.xy sends fields integer array
-            result = addConstVectorNode(fields, base, loc);
+            fields.offsets[0] = indexValue;
+            result = addConstVectorNode(loc, fields, base);
         } else if (base->isMatrix()) {
             // constant folding for matrices
-            result = addConstMatrixNode(index->getAsConstantUnion()->getConstArray()[0].getIConst(), base, loc);
+            result = addConstMatrixNode(loc, indexValue, base);
         }
     } else {
         // at least one of base and index is variable...
         if (index->getQualifier().storage == EvqConst) {
-            int indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst();
-            if (! base->isArray() && ((base->isVector() && base->getType().getVectorSize() <= indexValue) ||
-                                      (base->isMatrix() && base->getType().getMatrixCols() <= indexValue)))
-                error(loc, "", "[", "index out of range '%d'", index->getAsConstantUnion()->getConstArray()[0].getIConst());
-            if (base->isArray()) {
-                if (base->getType().getArraySize() == 0)
-                    updateMaxArraySize(loc, base, index->getAsConstantUnion()->getConstArray()[0].getIConst());
-                else if (index->getAsConstantUnion()->getConstArray()[0].getIConst() >= base->getType().getArraySize() ||
-                           index->getAsConstantUnion()->getConstArray()[0].getIConst() < 0)
-                    error(loc, "", "[", "array index out of range '%d'", index->getAsConstantUnion()->getConstArray()[0].getIConst());
-            }
+            if (base->isArray() && base->getType().getArraySize() == 0)
+                updateMaxArraySize(loc, base, indexValue);
             result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
         } else {
             if (base->isArray() && base->getType().getArraySize() == 0)
@@ -490,10 +487,12 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
     }
 
     if (result == 0) {
+        // Insert dummy error-recovery result
         TConstUnionArray unionArray(1);
         unionArray[0].setDConst(0.0);
         result = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), loc);
     } else {
+        // Insert valid dereferenced result
         TType newType;
         newType.shallowCopy(base->getType());
         if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst)
@@ -513,6 +512,29 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
     return result;
 }
 
+void TParseContext::checkIndex(TSourceLoc loc, const TType& type, int& index)
+{
+    if (index < 0) {
+        error(loc, "", "[", "index out of range '%d'", index);
+        index = 0;
+    } else if (type.isArray()) {
+        if (type.getArraySize() != 0 && index >= type.getArraySize()) {
+            error(loc, "", "[", "array index out of range '%d'", index);
+            index = type.getArraySize() - 1;
+        }
+    } else if (type.isVector()) {
+        if (index >= type.getVectorSize()) {
+            error(loc, "", "[", "vector index out of range '%d'", index);
+            index = type.getVectorSize() - 1;
+        }
+    } else if (type.isMatrix()) {
+        if (index >= type.getMatrixCols()) {
+            error(loc, "", "[", "matrix index out of range '%d'", index);
+            index = type.getMatrixCols() - 1;
+        }
+    }           
+}
+
 // for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms
 void TParseContext::handleIndexLimits(TSourceLoc loc, TIntermTyped* base, TIntermTyped* index)
 {
@@ -632,7 +654,7 @@ TIntermTyped* TParseContext::handleDotDereference(TSourceLoc loc, TIntermTyped*
         }
 
         if (base->getType().getQualifier().storage == EvqConst) { // constant folding for vector fields
-            result = addConstVectorNode(fields, base, loc);
+            result = addConstVectorNode(loc, fields, base);
             if (result == 0)
                 result = base;
             else
@@ -668,7 +690,7 @@ TIntermTyped* TParseContext::handleDotDereference(TSourceLoc loc, TIntermTyped*
             }
             if (fieldFound) {
                 if (base->getType().getQualifier().storage == EvqConst) {
-                    result = addConstStruct(field, base, loc);
+                    result = addConstStruct(loc, field, base);
                     if (result == 0)
                         result = base;
                     else {
@@ -3600,26 +3622,18 @@ TIntermNode* TParseContext::addSwitch(TSourceLoc loc, TIntermTyped* expression,
 // TODO: simplification: constant folding: these should use a follow a fully folded model now, and probably move to Constant.cpp scheme.
 
 //
-// This function returns the tree representation for the vector field(s) being accessed from a constant vector.
-// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
-// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
-// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
-// a constant matrix.
+// Make a constant scalar or vector node, representing a given constant vector and constant swizzle into it.
 //
-TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc loc)
+// The type of the returned node is still the original vector type; it needs to be corrected by the caller.
+//
+TIntermTyped* TParseContext::addConstVectorNode(TSourceLoc loc, TVectorFields& fields, TIntermTyped* node)
 {
-    TIntermTyped* typedNode;
-    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
-
-    TConstUnionArray unionArray;
-    if (tempConstantNode)
-        unionArray = tempConstantNode->getConstArray();
-    else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
+    if (! node->getAsConstantUnion()) {
         error(loc, "Cannot offset into the vector", "Error", "");
-
         return 0;
     }
 
+    const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray();
     TConstUnionArray constArray(fields.num);
 
     for (int i = 0; i < fields.num; i++) {
@@ -3630,52 +3644,45 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy
 
         constArray[i] = unionArray[fields.offsets[i]];
     }
-    typedNode = intermediate.addConstantUnion(constArray, node->getType(), loc);
 
-    return typedNode;
+    return intermediate.addConstantUnion(constArray, node->getType(), loc);
 }
 
 //
-// This function returns the column being accessed from a constant matrix. The values are retrieved from
-// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
-// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
-// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
+// Make a constant vector node, representing a given constant column 
+// from the given constant matrix.
 //
-TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc loc)
+// The type of the returned node is still the original matrix type; 
+// which needs to be corrected (dereferenced) by the caller.
+//
+TIntermTyped* TParseContext::addConstMatrixNode(TSourceLoc loc, int index, TIntermTyped* node)
 {
-    TIntermTyped* typedNode;
-    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+    TIntermConstantUnion* constNode = node->getAsConstantUnion();
 
     if (index >= node->getType().getMatrixCols()) {
         error(loc, "", "[", "matrix field selection out of range '%d'", index);
         index = 0;
     }
 
-    if (tempConstantNode) {
-        const TConstUnionArray& unionArray = tempConstantNode->getConstArray();
-        int size = tempConstantNode->getType().getMatrixRows();
-        // Note: the type is corrected (dereferenced) by the caller
-        typedNode = intermediate.addConstantUnion(TConstUnionArray(unionArray, size * index, size), tempConstantNode->getType(), loc);
+    if (constNode) {
+        const TConstUnionArray& unionArray = constNode->getConstArray();
+        int size = constNode->getType().getMatrixRows();
+        return intermediate.addConstantUnion(TConstUnionArray(unionArray, size * index, size), constNode->getType(), loc);
     } else {
         error(loc, "Cannot offset into the matrix", "Error", "");
-
         return 0;
     }
-
-    return typedNode;
 }
 
 
 //
-// This function returns an element of an array accessed from a constant array. The values are retrieved from
-// the symbol table and parse-tree is built for the type of the element. The input
-// to the function could either be a symbol node (a[0] where a is a constant array)that represents a
-// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
+// Make a constant node, representing the constant element of the constant array.
 //
-TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc loc)
+// The type of the returned node is still the original array type;
+// which needs to be corrected (dereferenced) by the caller.
+//
+TIntermTyped* TParseContext::addConstArrayNode(TSourceLoc loc, int index, TIntermTyped* node)
 {
-    TIntermTyped* typedNode;
-    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
     TType arrayElementType;
     arrayElementType.shallowCopy(node->getType());  // TODO: 4.3 simplification: arrays of arrays: combine this with deref.
     arrayElementType.dereference();
@@ -3685,18 +3692,14 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
         index = 0;
     }
 
-    int arrayElementSize = arrayElementType.getObjectSize();
-
-    if (tempConstantNode) {
-         typedNode = intermediate.addConstantUnion(TConstUnionArray(tempConstantNode->getConstArray(), arrayElementSize * index, arrayElementSize),
-                                                   tempConstantNode->getType(), loc);
+    if (node->getAsConstantUnion()) {
+        int arrayElementSize = arrayElementType.getObjectSize();
+        return intermediate.addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), arrayElementSize * index, arrayElementSize),
+                                             node->getType(), loc);
     } else {
         error(loc, "Cannot offset into the array", "Error", "");
-
         return 0;
     }
-
-    return typedNode;
 }
 
 
@@ -3705,16 +3708,13 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
 // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
 // function and returns the parse-tree with the values of the embedded/nested struct.
 //
-TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc loc)
+TIntermTyped* TParseContext::addConstStruct(TSourceLoc loc, TString& identifier, TIntermTyped* node)
 {
     TTypeList* fields = node->getType().getStruct();
-    TIntermTyped *typedNode;
     int instanceOffset = 0;
     int instanceSize;
-    unsigned int index = 0;
-    TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
 
-    for ( index = 0; index < fields->size(); ++index) {
+    for (size_t index = 0; index < fields->size(); ++index) {
         instanceSize = (*fields)[index].type->getObjectSize();
 
         if ((*fields)[index].type->getFieldName() == identifier)
@@ -3723,17 +3723,14 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n
         instanceOffset += instanceSize;
     }
 
-    if (tempConstantNode) {
-         typedNode = intermediate.addConstantUnion(TConstUnionArray(tempConstantNode->getConstArray(), instanceOffset, instanceSize),
-                                                   tempConstantNode->getType(), loc);
+    if (node->getAsConstantUnion()) {
+         return intermediate.addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), instanceOffset, instanceSize),
+                                              node->getType(), loc);
          // type will be changed in the calling function
     } else {
         error(loc, "Cannot offset into the structure", "Error", "");
-
         return 0;
     }
-
-    return typedNode;
 }
 
 } // end namespace glslang
index 6ae6456..2bade69 100644 (file)
@@ -81,6 +81,7 @@ public:
     void handlePragma(const char **tokens, int numTokens);
     TIntermTyped* handleVariable(TSourceLoc, TSymbol* symbol, TString* string);
     TIntermTyped* handleBracketDereference(TSourceLoc, TIntermTyped* base, TIntermTyped* index);
+    void checkIndex(TSourceLoc, const TType&, int& index);
     void handleIndexLimits(TSourceLoc, TIntermTyped* base, TIntermTyped* index);
     void handleInputArrayAccess(TSourceLoc, TIntermTyped* base);
     void checkInputArrayConsistency(TSourceLoc, bool tailOnly = false);
@@ -159,10 +160,10 @@ public:
     void updateTypedDefaults(TSourceLoc, const TQualifier&, const TString* id);
     void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
     TIntermNode* addSwitch(TSourceLoc, TIntermTyped* expression, TIntermAggregate* body);
-    TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
-    TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
-    TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc);
-    TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
+    TIntermTyped* addConstVectorNode(TSourceLoc, TVectorFields&, TIntermTyped*);
+    TIntermTyped* addConstMatrixNode(TSourceLoc, int index, TIntermTyped*);
+    TIntermTyped* addConstArrayNode(TSourceLoc, int index, TIntermTyped* node);
+    TIntermTyped* addConstStruct(TSourceLoc, TString& , TIntermTyped*);
 
     void updateMaxArraySize(TSourceLoc, TIntermNode*, int index);
 
index 872607b..342fca5 100644 (file)
@@ -118,28 +118,23 @@ void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
     if (oit->index >= instanceSize)
         return;
 
-    if (!oit->singleConstantParam) {
+    if (! oit->singleConstantParam) {
         int size = node->getType().getObjectSize();
     
         const TConstUnionArray& rightUnionArray = node->getConstArray();
-        for (int i=0; i < size; i++) {
+        for (int i = 0; i < size; i++) {
             if (oit->index >= instanceSize)
                 return;
             leftUnionArray[oit->index] = rightUnionArray[i];
 
-            (oit->index)++;
+            oit->index++;
         }
     } else {
-        int size, totalSize, matrixRows;
-        bool isMatrix = false;
-        size = oit->size;
-        matrixRows = oit->matrixRows;
-        isMatrix = oit->isMatrix;
-        totalSize = oit->index + size;
+        int endIndex = oit->index + oit->size;
         const TConstUnionArray& rightUnionArray = node->getConstArray();
-        if (! isMatrix) {
+        if (! oit->isMatrix) {
             int count = 0;
-            for (int i = oit->index; i < totalSize; i++) {
+            for (int i = oit->index; i < endIndex; i++) {
                 if (i >= instanceSize)
                     return;
 
@@ -150,21 +145,41 @@ void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
                 if (node->getType().getObjectSize() > 1)
                     count++;
             }
-        } else {  // for matrix constructors
-            int count = 0;
-            int index = oit->index;
-            for (int i = index; i < totalSize; i++) {
-                if (i >= instanceSize)
-                    return;
-                if (index - i == 0 || (i - index) % (matrixRows + 1) == 0 )
-                    leftUnionArray[i] = rightUnionArray[count];
-                else 
-                    leftUnionArray[i].setDConst(0.0);
-
-                (oit->index)++;
-
-                if (node->getType().getObjectSize() > 1)
-                    count++;                
+        } else {
+            // constructing a matrix, but from what?
+            if (node->isMatrix()) {
+                // Matrix from a matrix; oit has the outer matrix, node is the argument matrix.
+                // Traverse the outer, potentially bigger matrix, fill in missing pieces with the
+                // identity matrix.
+                for (int c = 0; c < oit->matrixCols; ++c) {
+                    for (int r = 0; r < oit->matrixRows; ++r) {
+                        int targetOffset = oit->index + c * oit->matrixRows + r;
+                        if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) {
+                            int srcOffset = c * node->getType().getMatrixRows() + r;
+                            leftUnionArray[targetOffset] = rightUnionArray[srcOffset];
+                        } else if (r == c)
+                            leftUnionArray[targetOffset].setDConst(1.0);
+                        else
+                            leftUnionArray[targetOffset].setDConst(0.0);
+                    }
+                }
+            } else {
+                // matrix from vector
+                int count = 0;
+                int index = oit->index;
+                for (int i = index; i < endIndex; i++) {
+                    if (i >= instanceSize)
+                        return;
+                    if (i == index || (i - index) % (oit->matrixRows + 1) == 0 )
+                        leftUnionArray[i] = rightUnionArray[count];
+                    else 
+                        leftUnionArray[i].setDConst(0.0);
+
+                    oit->index++;
+
+                    if (node->getType().getObjectSize() > 1)
+                        count++;                
+                }
             }
         }
     }