Initialize uninitialized locals in GLSL output

Guarantee that local variables are initialized before they are used
in GLSL output. In HLSL output all variables were already being
initialized.

Locals are initialized using an AST transform. The local variable init
can only be run after some simplification of the AST, so that it is
able to handle complex cases like:

for (int i[2], j = i[0]; i[0] < 3; ++i[0]) {
}

If we're dealing with ESSL 1.00 which lacks array constructors, in
this kind of case the uninitialized array initialization code needs to
be hoisted out of the loop init statement, and the code also needs to
make sure that j's initializer is run after i is initialized.

Another complex case involves nameless structs. This can be an issue
also in ESSL 3.00 and above:

for (struct { float f; } s; s.f < 1.0; ++s.f) {
}

Since the struct doesn't have a name, its constructor can not be used.
We solve this by initializing the struct members individually,
similarly to how arrays are initialized in ESSL 1.00.

Initializing local variables is disabled on Mac and Android for now.
On Mac, invalid behavior was exposed in the WebGL 2.0 tests when
enabling it. On Android, the dEQP test runs failed for an unknown
reason. Bugs have been opened to resolve these issues later.

BUG=angleproject:1966
TEST=angle_end2end_tests, WebGL conformance tests

Change-Id: Ic06927f5b6cc9619bc82c647ee966605cd80bab2
Reviewed-on: https://chromium-review.googlesource.com/504728
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/InitializeVariables.h b/src/compiler/translator/InitializeVariables.h
index 5b54689..1e6dfba 100644
--- a/src/compiler/translator/InitializeVariables.h
+++ b/src/compiler/translator/InitializeVariables.h
@@ -9,23 +9,31 @@
 
 #include <GLSLANG/ShaderLang.h>
 
+#include "compiler/translator/IntermNode.h"
+
 namespace sh
 {
-class TIntermBlock;
 class TSymbolTable;
 
 typedef std::vector<sh::ShaderVariable> InitVariableList;
 
-// Currently this function is only capable of initializing variables of basic types,
-// array of basic types, or struct of basic types.
+// Return a sequence of assignment operations to initialize "initializedSymbol". initializedSymbol
+// may be an array, struct or any combination of these, as long as it contains only basic types.
+TIntermSequence *CreateInitCode(const TIntermSymbol *initializedSymbol);
+
+// Initialize all uninitialized local variables, so that undefined behavior is avoided.
+void InitializeUninitializedLocals(TIntermBlock *root, int shaderVersion);
+
+// This function can initialize all the types that CreateInitCode is able to initialize. For struct
+// typed variables it requires that the struct is found from the symbolTable, which is usually not
+// the case for locally defined struct types.
 // For now it is used for the following two scenarios:
 //   1. initializing gl_Position;
-//   2. initializing ESSL 3.00 shaders' output variables (which might be structs).
-// Specifically, it's not feasible to make it work for local variables because if their
-// types are structs, we can't look into TSymbolTable to find the TType data.
+//   2. initializing ESSL 3.00 shaders' output variables.
 void InitializeVariables(TIntermBlock *root,
                          const InitVariableList &vars,
                          const TSymbolTable &symbolTable);
+
 }  // namespace sh
 
 #endif  // COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_