Initialize uninitialized globals in GLSL output

Initializing globals is done by the DeferGlobalInitializers AST
transformation, which makes sure that the global variable init
proceeds in the correct order. This is important since some global
variables may use other uninitialized globals in their initializers.

The global variable init is only done in case the WebGL shader spec is
being followed. This avoids adding global initializers twice in case
the same shader goes through multiple translations, assuming only one
of them is a WebGL shader translation.

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

Change-Id: Iea701d3ae40edc906abd87303f2aa27fd23bf55a
Reviewed-on: https://chromium-review.googlesource.com/509689
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/tests/gl_tests/GLSLTest.cpp b/src/tests/gl_tests/GLSLTest.cpp
index 95b27e3..c012011 100644
--- a/src/tests/gl_tests/GLSLTest.cpp
+++ b/src/tests/gl_tests/GLSLTest.cpp
@@ -2960,6 +2960,51 @@
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
+// Test that uninitialized global variables are initialized to 0.
+TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
+{
+    const std::string &fragmentShader =
+        "precision mediump float;\n"
+        "int result;\n"
+        "int i[2], j = i[0] + 1;\n"
+        "void main()\n"
+        "{\n"
+        "    result += j;\n"
+        "    if (result == 1)\n"
+        "    {\n"
+        "        gl_FragColor = vec4(0, 1, 0, 1);\n"
+        "    }\n"
+        "    else\n"
+        "    {\n"
+        "        gl_FragColor = vec4(1, 0, 0, 1);\n"
+        "    }\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Test that an uninitialized nameless struct in the global scope works.
+TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
+{
+    const std::string &fragmentShader =
+        "precision mediump float;\n"
+        "struct { float q; } b;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(1, 0, 0, 1);\n"
+        "    if (b.q == 0.0)\n"
+        "    {\n"
+        "        gl_FragColor = vec4(0, 1, 0, 1);\n"
+        "    }\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
 ANGLE_INSTANTIATE_TEST(GLSLTest,
                        ES2_D3D9(),