Flatten uniform arrays

This checkin adds a --flatten-uniform-arrays option which can break
uniform arrays of samplers, textures, or UBOs up into individual
scalars named (e.g) myarray[0], myarray[1], etc.  These appear as
individual linkage objects.

Code notes:

- shouldFlatten internally calls shouldFlattenIO, and shouldFlattenUniform,
  but is the only flattening query directly called.

- flattenVariable will handle structs or arrays (but not yet arrayed structs;
  this is tested an an error is generated).

- There's some error checking around unhandled situations.  E.g, flattening
  uniform arrays with initializer lists is not implemented.

- This piggybacks on as much of the existing mechanism for struct flattening
  as it can.  E.g, it uses the same flattenMap, and the same
  flattenAccess() method.

- handleAssign() has been generalized to cope with either structs or arrays.

- Extended test infrastructure to test flattening ability.
diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp
index 063e416..30af4fe 100644
--- a/StandAlone/StandAlone.cpp
+++ b/StandAlone/StandAlone.cpp
@@ -81,6 +81,7 @@
     EOptionReadHlsl           = (1 << 17),
     EOptionCascadingErrors    = (1 << 18),
     EOptionAutoMapBindings    = (1 << 19),
+    EOptionFlattenUniformArrays = (1 << 20),
 };
 
 //
@@ -285,6 +286,10 @@
                                lowerword == "auto-map-binding"  || 
                                lowerword == "amb") {
                         Options |= EOptionAutoMapBindings;
+                    } else if (lowerword == "flatten-uniform-arrays" || // synonyms
+                               lowerword == "flatten-uniform-array"  ||
+                               lowerword == "fua") {
+                        Options |= EOptionFlattenUniformArrays;
                     } else {
                         usage();
                     }
@@ -407,6 +412,10 @@
     // -o or -x makes no sense if there is no target binary
     if (binaryFileName && (Options & EOptionSpv) == 0)
         Error("no binary generation requested (e.g., -V)");
+
+    if ((Options & EOptionFlattenUniformArrays) != 0 &&
+        (Options & EOptionReadHlsl) == 0)
+        Error("uniform array flattening only valid when compiling HLSL source.");
 }
 
 //
@@ -532,6 +541,7 @@
         shader->setShiftSamplerBinding(baseSamplerBinding[compUnit.stage]);
         shader->setShiftTextureBinding(baseTextureBinding[compUnit.stage]);
         shader->setShiftUboBinding(baseUboBinding[compUnit.stage]);
+        shader->setFlattenUniformArrays((Options & EOptionFlattenUniformArrays) != 0);
 
         if (Options & EOptionAutoMapBindings)
             shader->setAutoMapBindings(true);
@@ -930,6 +940,9 @@
            "  --auto-map-bindings                     automatically bind uniform variables without\n"
            "                                          explicit bindings.\n"
            "  --amb                                   synonym for --auto-map-bindings\n"
+           "\n"
+           "  --flatten-uniform-arrays                flatten uniform array references to scalars\n"
+           "  --fua                                   synonym for --flatten-uniform-arrays\n"
            );
 
     exit(EFailUsage);